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, arc_mode=None): # If we are in arc_mode, do not report failures to perf dashboard. if arc_mode: self._test_failure_report_enable = False # We use kiosk mode to make sure Chrome is idle. self.add_failures('Graphics_Idle') with chrome.Chrome(logged_in=False, extra_browser_args=['--kiosk'], arc_mode=arc_mode): # Try to protect against runaway previous tests. if not utils.wait_for_idle_cpu(20.0, 0.1): logging.warning('Could not get idle CPU before running tests.') self._gpu_type = utils.get_gpu_family() self._cpu_type = utils.get_cpu_soc_family() self._board = utils.get_board() errors = '' errors += self.verify_graphics_dvfs() errors += self.verify_graphics_fbc() errors += self.verify_graphics_psr() errors += self.verify_graphics_gem_idle() errors += self.verify_graphics_i915_min_clock() errors += self.verify_graphics_rc6() errors += self.verify_lvds_downclock() errors += self.verify_short_blanking() if errors: raise error.TestFail('Failed: %s' % errors) self.remove_failures('Graphics_Idle')
def get_memory_keyvals(self): """ Reads the graphics memory values and returns them as keyvals. """ keyvals = {} # Get architecture type and list of sysfs fields to read. soc = utils.get_cpu_soc_family() arch = utils.get_cpu_arch() if arch == 'x86_64' or arch == 'i386': pci_vga_device = utils.run("lspci | grep VGA").stdout.rstrip('\n') if "Advanced Micro Devices" in pci_vga_device: soc = 'amdgpu' elif "Intel Corporation" in pci_vga_device: soc = 'i915' elif "Cirrus Logic" in pci_vga_device: # Used on qemu with kernels 3.18 and lower. Limited to 800x600 # resolution. soc = 'cirrus' else: pci_vga_device = utils.run('lshw -c video').stdout.rstrip() groups = re.search('configuration:.*driver=(\S*)', pci_vga_device) if groups and 'virtio' in groups.group(1): soc = 'virtio' if not soc in self.arch_fields: raise error.TestFail('Error: Architecture "%s" not yet supported.' % soc) fields = self.arch_fields[soc] for field_name in fields: possible_field_paths = fields[field_name] field_value = None for path in possible_field_paths: if utils.system('ls %s' % path): continue field_value = utils.system_output('cat %s' % path) break if not field_value: logging.error('Unable to find any sysfs paths for field "%s"', field_name) self.num_errors += 1 continue parsed_results = GraphicsKernelMemory._parse_sysfs(field_value) for key in parsed_results: keyvals['%s_%s' % (field_name, key)] = parsed_results[key] if 'bytes' in parsed_results and parsed_results['bytes'] == 0: logging.error('%s reported 0 bytes', field_name) self.num_errors += 1 keyvals['meminfo_MemUsed'] = (utils.read_from_meminfo('MemTotal') - utils.read_from_meminfo('MemFree')) keyvals['meminfo_SwapUsed'] = (utils.read_from_meminfo('SwapTotal') - utils.read_from_meminfo('SwapFree')) return keyvals
def run_once(self, arc_mode=None): # If we are in arc_mode, do not report failures to perf dashboard. if arc_mode: self._test_failure_report_enable = False self.add_failures('graphics_Idle') with chrome.Chrome(logged_in=True, arc_mode=arc_mode) as cr: # The New Tab Page contains the Google doodle which can cause # arbitrary side effects. Hide it by going to a neutral page. if not cr.browser.tabs: cr.browser.tabs.New() tab = cr.browser.tabs[0] tab.Navigate('chrome://version') # Try to protect against runaway previous tests. if not utils.wait_for_idle_cpu(60.0, 0.1): logging.warning('Could not get idle CPU before running tests.') self._gpu_type = utils.get_gpu_family() self._cpu_type = utils.get_cpu_soc_family() self._board = utils.get_board() errors = '' errors += self.verify_graphics_dvfs() errors += self.verify_graphics_fbc() errors += self.verify_graphics_psr() errors += self.verify_graphics_gem_idle() errors += self.verify_graphics_i915_min_clock() errors += self.verify_graphics_rc6() errors += self.verify_lvds_downclock() errors += self.verify_short_blanking() if errors: raise error.TestFail('Failed: %s' % errors) self.remove_failures('graphics_Idle')
def verify_graphics_rc6(self): """ On systems which support RC6 (non atom), check that we are able to get into rc6; idle before doing so, and retry every second for 20 seconds.""" logging.info('Running verify_graphics_rc6') # TODO(ihf): Implement on baytrail/braswell using residency counters. # But note the format changed since SNB, so this will be complex. if (utils.get_cpu_soc_family() == 'x86_64' and self._gpu_type != 'pinetrail' and self._gpu_type != 'baytrail' and self._gpu_type != 'braswell'): tries = 0 found = False param_path = self.get_valid_path(RC6_PATHS) if not param_path: return 'RC6_PATHS not found.' while found == False and tries < 20: time.sleep(1) with open(param_path, 'r') as drpc_info_file: for line in drpc_info_file: match = re.search(r'Current RC state: (.*)', line) if match and match.group(1) == 'RC6': found = True break tries += 1 if not found: return self.handle_error('Error: did not see the GPU in RC6.', param_path) return ''
def verify_graphics_gem_idle(self): """ On systems which have i915, check that we can get all gem objects to become idle (i.e. the i915_gem_active list need to go to 0); idle before doing so, and retry every second for 20 seconds.""" logging.info('Running verify_graphics_gem_idle') if (utils.get_cpu_soc_family() == 'x86_64' and self._gpu_type != 'pinetrail'): tries = 0 found = False gem_path = self.get_valid_path(GEM_PATHS) if not gem_path: return 'GEM_PATHS not found.' while not found and tries < 240: time.sleep(0.25) with open(gem_path, 'r') as gem_file: for line in gem_file: if re.search('Total 0 objects', line): found = True break tries += 1 if not found: utils.log_process_activity() logging.error('Error: did not reach 0 gem actives.') return 'Did not reach 0 gem actives. ' return ''
def verify_graphics_psr(self): """ On systems which support PSR, check that we can get into PSR; idle before doing so, and retry every second for 20 seconds.""" logging.info('Running verify_graphics_psr') if utils.get_cpu_soc_family() != 'x86_64': return '' tries = 0 found = False param_path = self.get_valid_path(PSR_PATHS) if not param_path: logging.warning("PSR_PATHS not found.") return '' kernel_version = utils.get_kernel_version()[0:4].rstrip(".") logging.info('Kernel version: %s', kernel_version) # First check if PSR is enabled on the device so # we can watch for the active values with open(param_path, 'r') as psr_info_file: match = None for line in psr_info_file: match = re.search(r'Enabled: yes', line) if match: logging.info('PSR enabled') break if not match: logging.warning('PSR not enabled') return '' while not found and tries < 20: time.sleep(1) with open(param_path, 'r') as psr_info_file: for line in psr_info_file: # Kernels 4.4 and up if common_utils.compare_versions(kernel_version, '4.4') != -1: match = re.search(r'PSR status: .* \[SRDENT', line) if match: found = True logging.info('Found active with kernel >= 4.4') break # 3.18 kernel elif kernel_version == '3.18': match = re.search(r'Performance_Counter: 0', line) if match: found = True logging.info('Found active with 3.18 kernel') break # Older kernels (up to 3.14) else: match = re.search(r'Performance_Counter: ([\d])+', line) if match and int(match.group(1)) > 0: found = True logging.info('Found active with kernel <= 3.14') break tries += 1 if not found: return self.handle_error('Did not see PSR activity. ', param_path) return ''
def run_once(self): num_errors = 0 keyvals = {} # These are tests to run for all platforms. tests_common = ['modetest'] # Determine which tests to run based on the architecture type. tests_exynos5 = ['kmstest'] tests_mediatek = ['kmstest'] tests_rockchip = ['kmstest'] arch_tests = { 'amd': [], 'arm': [], 'exynos5': tests_exynos5, 'i386': [], 'mediatek': tests_mediatek, 'rockchip': tests_rockchip, 'tegra': [], 'x86_64': [] } soc = utils.get_cpu_soc_family() if not soc in arch_tests: raise error.TestFail('Error: Architecture "%s" not supported.', soc) elif soc == 'tegra': logging.warning('Tegra does not support DRM.') return tests = tests_common + arch_tests[soc] # If UI is running, we must stop it and restore later. self._services.stop_services() for test in tests: # Make sure the test exists on this system. Not all tests may be # present on a given system. if utils.system('which %s' % test): logging.error('Could not find test %s.', test) keyvals[test] = 'NOT FOUND' num_errors += 1 continue # Run the test and check for success based on return value. return_value = utils.system(test) if return_value: logging.error('%s returned %d', test, return_value) num_errors += 1 keyvals[test] = 'FAILED' else: keyvals[test] = 'PASSED' self.write_perf_keyval(keyvals) if num_errors > 0: raise error.TestFail('Failed: %d libdrm tests failed.' % num_errors)
def verify_graphics_gem_idle(self): """ On systems which have i915, check that we can get all gem objects to become idle (i.e. the i915_gem_active list or i915_gem_objects client/process gem object counts need to go to 0); idle before doing so, and retry every second for 20 seconds.""" logging.info('Running verify_graphics_gem_idle') if utils.get_cpu_soc_family() == 'x86_64': tries = 0 found = False per_process_check = False gem_path = self.get_valid_path(GEM_PATHS) if not gem_path: gem_path = self.get_valid_path(GEM_OBJECTS_PATHS) if gem_path: per_process_check = True else: return 'GEM_PATHS not found.' # Checks 4.4 and later kernels if per_process_check: while not found and tries < 240: time.sleep(0.25) gem_objects_idle = False gem_active_search = False with open(gem_path, 'r') as gem_file: for line in gem_file: if gem_active_search: if re.search('\(0 active,', line): gem_objects_idle = True else: gem_objects_idle = False break elif line == '\n': gem_active_search = True if gem_objects_idle: found = True tries += 1 # Checks pre 4.4 kernels else: while not found and tries < 240: time.sleep(0.25) with open(gem_path, 'r') as gem_file: for line in gem_file: if re.search('Total 0 objects', line): found = True break tries += 1 if not found: return self.handle_error('Did not reach 0 gem actives. ', gem_path) return ''
def run_once(self, doctest=False): """ Run the test. :param doctest: If true we will just run our doctests. We'll set these globals to help our tests: - _testobj: An instance of this object. - _info_io: A StringIO that's stuffed into logging.info so we can see what was written there. ... """ if doctest: import doctest, inspect, StringIO global _testobj, _info_io # Keep a backup of _get_regid_to_val() since tests will clobber. old_get_regid_to_val = self._get_regid_to_val # Mock out logging.info to help tests. _info_io = StringIO.StringIO() old_logging_info = logging.info logging.info = lambda fmt, *args: _info_io.write(fmt % args) # Stash an object in a global to help tests _testobj = self try: failure_count, test_count = doctest.testmod( inspect.getmodule(self), optionflags=doctest.ELLIPSIS) finally: logging.info = old_logging_info # Technically don't need to clean this up, but let's be nice. self._get_regid_to_val = old_get_regid_to_val logging.info("Doctest ran %d tests, had %d failures", test_count, failure_count) return if utils.get_cpu_soc_family() != 'arm': raise error.TestNAError('Applicable to ARM processors only') cpuinfo = self._parse_cpu_info(utils.read_file('/proc/cpuinfo')) for cpu_id in sorted(cpuinfo.keys()): self._check_one_cpu(cpuinfo[cpu_id]) sys_power.do_suspend(self.SECS_TO_SUSPEND) for cpu_id in sorted(cpuinfo.keys()): self._check_one_cpu(cpuinfo[cpu_id])
def initialize(self): self._board = utils.get_board() self._cpu_type = utils.get_cpu_soc_family() self._gpu_type = utils.get_gpu_family() # deqp may depend on libraries that are present only on test images. # Those libraries are installed in /usr/local. self._env = os.environ.copy() old_ld_path = self._env.get('LD_LIBRARY_PATH', '') if old_ld_path: self._env[ 'LD_LIBRARY_PATH'] = '/usr/local/lib:/usr/local/lib64:' + old_ld_path else: self._env['LD_LIBRARY_PATH'] = '/usr/local/lib:/usr/local/lib64' # Determine which executable should be run. Right now never egl. major, minor = graphics_utils.get_gles_version() logging.info('Found gles%d.%d.', major, minor) if major is None or minor is None: raise error.TestFail( 'Failed: Could not get gles version information (%d, %d).' % (major, minor)) if major >= 2: self._can_run_executables.append('gles2/deqp-gles2') if major >= 3: self._can_run_executables.append('gles3/deqp-gles3') if major > 3 or minor >= 1: self._can_run_executables.append('gles31/deqp-gles31') # If libvulkan is installed, then assume the board supports vulkan. has_libvulkan = False for libdir in ('/usr/lib', '/usr/lib64', '/usr/local/lib', '/usr/local/lib64'): if os.path.exists(os.path.join(libdir, 'libvulkan.so')): has_libvulkan = True if (has_libvulkan and os.path.exists( '/usr/local/deqp/external/vulkancts/modules/vulkan/deqp-vk')): self._can_run_executables.append( 'external/vulkancts/modules/vulkan/deqp-vk') self._services = service_stopper.ServiceStopper(['ui', 'powerd']) # Valid choices are fbo and pbuffer. The latter avoids dEQP assumptions. self._surface = 'pbuffer'
def verify_graphics_i915_min_clock(self): """ On i915 systems, check that we get into the lowest clock frequency; idle before doing so, and retry every second for 20 seconds.""" logging.info('Running verify_graphics_i915_min_clock') # TODO(benzh): enable once crbug.com/719040 is fixed. if self._gpu_type == 'baytrail' and utils.count_cpus() == 4: logging.info('Waived min clock check due to crbug.com/719040') return '' if (utils.get_cpu_soc_family() == 'x86_64' and self._gpu_type != 'pinetrail'): tries = 0 found = False param_path = self.get_valid_path(CLOCK_PATHS) if not param_path: return 'CLOCK_PATHS not found.' while not found and tries < 80: time.sleep(0.25) with open(param_path, 'r') as delayinfo_file: for line in delayinfo_file: # This file has a different format depending on the # board, so we parse both. Also, it would be tedious # to add the minimum clock for each board, so instead # we use 650MHz which is the max of the minimum clocks. match = re.search(r'CAGF: (.*)MHz', line) if match and int(match.group(1)) <= 650: found = True break match = re.search(r'current GPU freq: (.*) MHz', line) if match and int(match.group(1)) <= 650: found = True break tries += 1 if not found: return self.handle_error('Did not see the min i915 clock. ', param_path) return ''
def get_memory_keyvals(self): """ Reads the graphics memory values and returns them as keyvals. """ keyvals = {} # Get architecture type and list of sysfs fields to read. arch = utils.get_cpu_soc_family() if not arch in self.arch_fields: raise error.TestFail('Architecture "%s" not yet supported.' % arch) fields = self.arch_fields[arch] for field_name in fields: possible_field_paths = fields[field_name] field_value = None for path in possible_field_paths: if utils.system('ls %s' % path): continue field_value = utils.system_output('cat %s' % path) break if not field_value: logging.error('Unable to find any sysfs paths for field "%s"', field_name) self.num_errors += 1 continue parsed_results = GraphicsKernelMemory._parse_sysfs(field_value) for key in parsed_results: keyvals['%s_%s' % (field_name, key)] = parsed_results[key] if 'bytes' in parsed_results and parsed_results['bytes'] == 0: logging.error('%s reported 0 bytes', field_name) self.num_errors += 1 keyvals['meminfo_MemUsed'] = (utils.read_from_meminfo('MemTotal') - utils.read_from_meminfo('MemFree')) keyvals['meminfo_SwapUsed'] = (utils.read_from_meminfo('SwapTotal') - utils.read_from_meminfo('SwapFree')) return keyvals
def run_once(self): # Try to protect against runaway previous tests. if not utils.wait_for_idle_cpu(20.0, 0.1): logging.warning('Could not get idle CPU before running tests.') # We use kiosk mode to make sure Chrome is idle. with chrome.Chrome(logged_in=False, extra_browser_args=['--kiosk']): self._gpu_type = utils.get_gpu_family() self._cpu_type = utils.get_cpu_soc_family() self._board = utils.get_board() errors = '' errors += self.verify_graphics_dvfs() errors += self.verify_graphics_fbc() errors += self.verify_graphics_psr() errors += self.verify_graphics_gem_idle() errors += self.verify_graphics_i915_min_clock() errors += self.verify_graphics_rc6() errors += self.verify_lvds_downclock() errors += self.verify_short_blanking() if errors: raise error.TestFail(errors)
def initialize(self): super(graphics_dEQP, self).initialize() self._api_helper = graphics_utils.GraphicsApiHelper() self._board = utils.get_board() self._cpu_type = utils.get_cpu_soc_family() self._gpu_type = utils.get_gpu_family() # deqp may depend on libraries that are present only on test images. # Those libraries are installed in /usr/local. self._env = os.environ.copy() old_ld_path = self._env.get('LD_LIBRARY_PATH', '') if old_ld_path: self._env['LD_LIBRARY_PATH'] = '/usr/local/lib:/usr/local/lib64:' + old_ld_path else: self._env['LD_LIBRARY_PATH'] = '/usr/local/lib:/usr/local/lib64' self._services = service_stopper.ServiceStopper(['ui', 'powerd']) # Valid choices are fbo and pbuffer. The latter avoids dEQP assumptions. self._surface = 'pbuffer' self._services.stop_services()
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 initialize(self): self._gpu_type = utils.get_gpu_family() self._cpu_type = utils.get_cpu_soc_family() self._board = utils.get_board() self._services = service_stopper.ServiceStopper(['ui', 'powerd'])
def run_once(self, expect_me_present=True): """Fail unless the ME is locked. @param expect_me_present: False means the system has no ME. """ cpu_arch = utils.get_cpu_arch() if cpu_arch == "arm": raise error.TestNAError( 'This test is not applicable, ' 'because an ARM device has been detected. ' 'ARM devices do not have an ME (Management Engine)') cpu_family = utils.get_cpu_soc_family() if cpu_family == "amd": raise error.TestNAError( 'This test is not applicable, ' 'because an AMD device has been detected. ' 'AMD devices do not have an ME (Management Engine)') # If sw wp is on, and the ME regions are unlocked, they won't be # writable so will appear locked. if self.determine_sw_wp_status(): raise error.TestFail('Software wp is enabled. Please disable ' 'software wp prior to running this test.') # See if the system even has an ME, and whether we expected that. if self.has_ME(): if not expect_me_present: raise error.TestFail('We expected no ME, but found one anyway') else: if expect_me_present: raise error.TestNAError("No ME found. That's probably wrong.") else: logging.info('We expected no ME and we have no ME, so pass.') return # Make sure manufacturing mode is off. self.check_manufacturing_mode() # Read the image using flashrom. self.flashrom(args=('-r', self.BIOS_FILE)) # Use 'IFWI' fmap region as a proxy for a device which doesn't # have a dedicated ME region in the boot media. r = utils.run('dump_fmap', args=('-p', self.BIOS_FILE)) is_IFWI_platform = r.stdout.find("IFWI") >= 0 # Get the bios image and extract the ME components logging.info('Pull the ME components from the BIOS...') dump_fmap_args = ['-x', self.BIOS_FILE, 'SI_DESC'] inaccessible_sections = [] if is_IFWI_platform: inaccessible_sections.append('DEVICE_EXTENSION') else: inaccessible_sections.append('SI_ME') dump_fmap_args.extend(inaccessible_sections) utils.run('dump_fmap', args=tuple(dump_fmap_args)) # So far, so good, but we need to be certain. Rather than parse what # flashrom tells us about the ME-related registers, we'll just try to # change the ME components. We shouldn't be able to. self.try_to_rewrite('SI_DESC') for sectname in inaccessible_sections: self.check_region_inaccessible(sectname)