diff options
Diffstat (limited to 'tests')
165 files changed, 29567 insertions, 4933 deletions
diff --git a/tests/.gitignore b/tests/.gitignore deleted file mode 100644 index 1a6795bc..00000000 --- a/tests/.gitignore +++ /dev/null @@ -1,78 +0,0 @@ -flip_test -drm_vma_limiter -drm_vma_limiter_cached -drm_vma_limiter_cpu -drm_vma_limiter_gtt -gem_bad_address -gem_bad_batch -gem_bad_blit -gem_bad_length -gem_basic -gem_cs_prefetch -gem_cpu_concurrent_blit -gem_ctx_bad_destroy -gem_ctx_bad_exec -gem_ctx_basic -gem_ctx_create -gem_ctx_exec -gem_double_irq_loop -gem_dummy_reloc_loop -gem_exec_bad_domains -gem_exec_blt -gem_exec_faulting_reloc -gem_exec_nop -gem_fenced_exec_thrash -gem_fence_thrash -gem_flink -gem_gtt_speed -gem_gtt_concurrent_blit -gem_gtt_cpu_tlb -gem_hang -gem_hangcheck_forcewake -gem_largeobject -gem_linear_blits -gem_mmap -gem_mmap_gtt -gem_mmap_offset_exhaustion -gem_partial_pwrite_pread -gem_pipe_control_store_loop -gem_pread_after_blit -gem_pwrite -gem_readwrite -gem_reloc_vs_gpu -gem_reg_read -gem_ringfill -gem_ring_sync_loop -gem_set_tiling_vs_blt -gem_set_tiling_vs_gtt -gem_set_tiling_vs_pwrite -gem_storedw_batches_loop -gem_storedw_loop_blt -gem_storedw_loop_bsd -gem_storedw_loop_render -gem_stress -gem_tiled_blits -gem_tiled_fence_blits -gem_tiled_partial_pwrite_pread -gem_tiled_pread -gem_tiled_pread_pwrite -gem_tiled_swapping -gem_unfence_active_buffers -gem_unref_active_buffers -gem_vmap_blits -gem_wait_render_timeout -gen3_mixed_blits -gen3_render_linear_blits -gen3_render_mixed_blits -gen3_render_tiledx_blits -gen3_render_tiledy_blits -getclient -getstats -getversion -prime_nv_api -prime_nv_pcopy -prime_nv_test -prime_self_import -testdisplay -sysfs_rc6_residency -# Please keep sorted alphabetically diff --git a/tests/1080p-left.png b/tests/1080p-left.png Binary files differnew file mode 100644 index 00000000..b08f0715 --- /dev/null +++ b/tests/1080p-left.png diff --git a/tests/1080p-right.png b/tests/1080p-right.png Binary files differnew file mode 100644 index 00000000..ea4cd8aa --- /dev/null +++ b/tests/1080p-right.png diff --git a/tests/Makefile.am b/tests/Makefile.am index e29a383a..71ecdf20 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,144 +1,69 @@ -noinst_PROGRAMS = \ - gem_stress \ - $(TESTS_progs) \ - $(HANG) \ - $(NULL) +include Makefile.sources if HAVE_NOUVEAU -NOUVEAU_TESTS = \ - prime_nv_api \ - prime_nv_pcopy \ - prime_nv_test + TESTS_progs_M += $(NOUVEAU_TESTS_M) endif -TESTS_progs = \ - getversion \ - getclient \ - getstats \ - gem_basic \ - gem_cpu_concurrent_blit \ - gem_gtt_concurrent_blit \ - gem_exec_nop \ - gem_exec_blt \ - gem_exec_bad_domains \ - gem_exec_faulting_reloc \ - gem_flink \ - gem_readwrite \ - gem_ringfill \ - gem_mmap \ - gem_mmap_gtt \ - gem_mmap_offset_exhaustion \ - gem_pwrite \ - gem_pread_after_blit \ - gem_set_tiling_vs_blt \ - gem_set_tiling_vs_gtt \ - gem_set_tiling_vs_pwrite \ - gem_tiled_pread \ - gem_tiled_pread_pwrite \ - gem_tiled_partial_pwrite_pread \ - gem_tiled_swapping \ - gem_partial_pwrite_pread \ - gem_linear_blits \ - gem_vmap_blits \ - gem_tiled_blits \ - gem_tiled_fence_blits \ - gem_largeobject \ - gem_bad_length \ - gem_fence_thrash \ - gem_fenced_exec_thrash \ - gem_gtt_speed \ - gem_gtt_cpu_tlb \ - gem_cs_prefetch \ - gen3_render_linear_blits \ - gen3_render_tiledx_blits \ - gen3_render_tiledy_blits \ - gen3_render_mixed_blits \ - gen3_mixed_blits \ - gem_storedw_loop_render \ - gem_storedw_loop_blt \ - gem_storedw_loop_bsd \ - gem_storedw_batches_loop \ - gem_dummy_reloc_loop \ - gem_double_irq_loop \ - gem_ring_sync_loop \ - gem_pipe_control_store_loop \ - gem_unfence_active_buffers \ - gem_unref_active_buffers \ - gem_reloc_vs_gpu \ - drm_vma_limiter \ - drm_vma_limiter_cpu \ - drm_vma_limiter_gtt \ - drm_vma_limiter_cached \ - sysfs_rc6_residency \ - flip_test \ - gem_wait_render_timeout \ - gem_ctx_create \ - gem_ctx_bad_destroy \ - gem_ctx_exec \ - gem_ctx_bad_exec \ - gem_ctx_basic \ - gem_reg_read \ - $(NOUVEAU_TESTS) \ - prime_self_import \ - $(NULL) +if BUILD_TESTS +all-local: single-tests.txt multi-tests.txt -# IMPORTANT: The ZZ_ tests need to be run last! -# ... and make can't deal with inlined comments ... -TESTS_scripts = \ - debugfs_reader \ - debugfs_emon_crash \ - sysfs_l3_parity \ - sysfs_edid_timing \ - module_reload \ - ZZ_check_dmesg \ - ZZ_hangman \ - $(NULL) +list-single-tests: + @echo TESTLIST + @echo ${single_kernel_tests} + @echo END TESTLIST -kernel_tests = \ - $(TESTS_progs) \ - $(TESTS_scripts) \ - $(NULL) +list-multi-tests: + @echo TESTLIST + @echo ${multi_kernel_tests} + @echo END TESTLIST -TESTS = \ - $(NULL) +single-tests.txt: Makefile.sources + @echo TESTLIST > $@ + @echo ${single_kernel_tests} >> $@ + @echo END TESTLIST >> $@ -test: - whoami | grep root || ( echo ERROR: not running as root; exit 1 ) - ./check_drm_clients - make TESTS="${kernel_tests}" check +multi-tests.txt: Makefile.sources + @echo TESTLIST > $@ + @echo ${multi_kernel_tests} >> $@ + @echo END TESTLIST >> $@ -HANG = \ - gem_bad_batch \ - gem_hang \ - gem_bad_blit \ - gem_bad_address \ - $(NULL) +EXTRA_PROGRAMS = $(TESTS_progs) $(TESTS_progs_M) $(HANG) $(TESTS_testsuite) +EXTRA_DIST = $(TESTS_scripts) $(TESTS_scripts_M) $(scripts) $(IMAGES) $(common_files) -EXTRA_PROGRAMS = $(TESTS_progs) $(HANG) -EXTRA_DIST = $(TESTS_scripts) drm_lib.sh check_drm_clients debugfs_wedged -CLEANFILES = $(EXTRA_PROGRAMS) +CLEANFILES = $(EXTRA_PROGRAMS) single-tests.txt multi-tests.txt AM_CFLAGS = $(DRM_CFLAGS) $(CWARNFLAGS) \ -I$(srcdir)/.. \ - -I$(srcdir)/../lib -LDADD = ../lib/libintel_tools.la $(PCIACCESS_LIBS) $(DRM_LIBS) - -testdisplay_SOURCES = \ - testdisplay.c \ - testdisplay.h \ - testdisplay_hotplug.c \ + -I$(srcdir)/../lib \ + -include "$(srcdir)/../lib/check-ndebug.h" \ + -include "$(top_builddir)/version.h" \ + -DIGT_DATADIR=\""$(abs_srcdir)"\" \ $(NULL) -TESTS_progs += testdisplay +LDADD = ../lib/libintel_tools.la $(PCIACCESS_LIBS) $(DRM_LIBS) + LDADD += $(CAIRO_LIBS) $(LIBUDEV_LIBS) $(GLIB_LIBS) AM_CFLAGS += $(CAIRO_CFLAGS) $(LIBUDEV_CFLAGS) $(GLIB_CFLAGS) +gem_close_race_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) +gem_close_race_LDADD = $(LDADD) -lpthread +gem_ctx_basic_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) +gem_ctx_basic_LDADD = $(LDADD) -lpthread gem_fence_thrash_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) gem_fence_thrash_LDADD = $(LDADD) -lpthread +gem_flink_race_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) +gem_flink_race_LDADD = $(LDADD) -lpthread +gem_threaded_access_tiled_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) +gem_threaded_access_tiled_LDADD = $(LDADD) -lpthread +gem_tiled_swapping_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) +gem_tiled_swapping_LDADD = $(LDADD) -lpthread +prime_self_import_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) +prime_self_import_LDADD = $(LDADD) -lpthread +gen7_forcewake_mt_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) +gen7_forcewake_mt_LDADD = $(LDADD) -lpthread gem_wait_render_timeout_LDADD = $(LDADD) -lrt - -gem_ctx_basic_LDADD = $(LDADD) -lpthread +kms_flip_LDADD = $(LDADD) -lrt -lpthread prime_nv_test_CFLAGS = $(AM_CFLAGS) $(DRM_NOUVEAU_CFLAGS) prime_nv_test_LDADD = $(LDADD) $(DRM_NOUVEAU_LIBS) @@ -146,3 +71,5 @@ prime_nv_api_CFLAGS = $(AM_CFLAGS) $(DRM_NOUVEAU_CFLAGS) prime_nv_api_LDADD = $(LDADD) $(DRM_NOUVEAU_LIBS) prime_nv_pcopy_CFLAGS = $(AM_CFLAGS) $(DRM_NOUVEAU_CFLAGS) prime_nv_pcopy_LDADD = $(LDADD) $(DRM_NOUVEAU_LIBS) +endif + diff --git a/tests/Makefile.in b/tests/Makefile.in new file mode 100644 index 00000000..5af503a8 --- /dev/null +++ b/tests/Makefile.in @@ -0,0 +1,3361 @@ +# Makefile.in generated by automake 1.13.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +DIST_COMMON = $(srcdir)/Makefile.sources $(srcdir)/Makefile.in \ + $(srcdir)/Makefile.am $(top_srcdir)/build-aux/depcomp \ + $(top_srcdir)/build-aux/test-driver +noinst_PROGRAMS = gem_alive$(EXEEXT) gem_stress$(EXEEXT) \ + ddi_compute_wrpll$(EXEEXT) $(am__EXEEXT_1) $(am__EXEEXT_4) \ + $(am__EXEEXT_5) $(am__EXEEXT_6) +TESTS = $(am__EXEEXT_6) +XFAIL_TESTS = igt_no_exit$(EXEEXT) igt_no_exit_list_only$(EXEEXT) \ + igt_no_subtest$(EXEEXT) +@HAVE_NOUVEAU_TRUE@am__append_1 = $(NOUVEAU_TESTS_M) +@BUILD_TESTS_TRUE@EXTRA_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_4) \ +@BUILD_TESTS_TRUE@ $(am__EXEEXT_5) $(am__EXEEXT_6) +subdir = tests +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_pkg_swig.m4 \ + $(top_srcdir)/m4/ax_python_devel.m4 \ + $(top_srcdir)/m4/ax_swig_python.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__EXEEXT_1 = core_getclient$(EXEEXT) core_getstats$(EXEEXT) \ + core_getversion$(EXEEXT) drm_vma_limiter$(EXEEXT) \ + drm_vma_limiter_cached$(EXEEXT) drm_vma_limiter_cpu$(EXEEXT) \ + drm_vma_limiter_gtt$(EXEEXT) gem_bad_length$(EXEEXT) \ + gem_cpu_reloc$(EXEEXT) gem_cs_prefetch$(EXEEXT) \ + gem_ctx_bad_destroy$(EXEEXT) gem_ctx_basic$(EXEEXT) \ + gem_ctx_create$(EXEEXT) gem_double_irq_loop$(EXEEXT) \ + gem_exec_big$(EXEEXT) gem_exec_blt$(EXEEXT) \ + gem_exec_lut_handle$(EXEEXT) gem_fd_exhaustion$(EXEEXT) \ + gem_gtt_cpu_tlb$(EXEEXT) gem_gtt_hog$(EXEEXT) \ + gem_gtt_speed$(EXEEXT) gem_hangcheck_forcewake$(EXEEXT) \ + gem_largeobject$(EXEEXT) gem_lut_handle$(EXEEXT) \ + gem_mmap_offset_exhaustion$(EXEEXT) gem_media_fill$(EXEEXT) \ + gem_pin$(EXEEXT) gem_reg_read$(EXEEXT) \ + gem_render_copy$(EXEEXT) gem_render_copy_redux$(EXEEXT) \ + gem_render_linear_blits$(EXEEXT) \ + gem_render_tiled_blits$(EXEEXT) gem_ring_sync_copy$(EXEEXT) \ + gem_ring_sync_loop$(EXEEXT) gem_multi_bsd_sync_loop$(EXEEXT) \ + gem_seqno_wrap$(EXEEXT) gem_set_tiling_vs_gtt$(EXEEXT) \ + gem_set_tiling_vs_pwrite$(EXEEXT) \ + gem_storedw_loop_blt$(EXEEXT) gem_storedw_loop_bsd$(EXEEXT) \ + gem_storedw_loop_render$(EXEEXT) \ + gem_storedw_loop_vebox$(EXEEXT) \ + gem_threaded_access_tiled$(EXEEXT) \ + gem_tiled_fence_blits$(EXEEXT) gem_tiled_pread$(EXEEXT) \ + gem_tiled_pread_pwrite$(EXEEXT) gem_tiled_swapping$(EXEEXT) \ + gem_tiling_max_stride$(EXEEXT) \ + gem_unfence_active_buffers$(EXEEXT) \ + gem_unref_active_buffers$(EXEEXT) gem_userptr_blits$(EXEEXT) \ + gem_wait_render_timeout$(EXEEXT) gen3_mixed_blits$(EXEEXT) \ + gen3_render_linear_blits$(EXEEXT) \ + gen3_render_mixed_blits$(EXEEXT) \ + gen3_render_tiledx_blits$(EXEEXT) \ + gen3_render_tiledy_blits$(EXEEXT) gen7_forcewake_mt$(EXEEXT) \ + kms_sink_crc_basic$(EXEEXT) kms_fence_pin_leak$(EXEEXT) \ + pm_psr$(EXEEXT) pm_rc6_residency$(EXEEXT) prime_udl$(EXEEXT) \ + testdisplay$(EXEEXT) +am__EXEEXT_2 = prime_nv_api$(EXEEXT) prime_nv_pcopy$(EXEEXT) \ + prime_nv_test$(EXEEXT) +@HAVE_NOUVEAU_TRUE@am__EXEEXT_3 = $(am__EXEEXT_2) +am__EXEEXT_4 = core_get_client_auth$(EXEEXT) drv_suspend$(EXEEXT) \ + drv_hangman$(EXEEXT) gem_bad_reloc$(EXEEXT) gem_basic$(EXEEXT) \ + gem_caching$(EXEEXT) gem_close_race$(EXEEXT) \ + gem_concurrent_blit$(EXEEXT) gem_cs_tlb$(EXEEXT) \ + gem_ctx_bad_exec$(EXEEXT) gem_ctx_exec$(EXEEXT) \ + gem_dummy_reloc_loop$(EXEEXT) gem_evict_alignment$(EXEEXT) \ + gem_evict_everything$(EXEEXT) gem_exec_bad_domains$(EXEEXT) \ + gem_exec_faulting_reloc$(EXEEXT) gem_exec_nop$(EXEEXT) \ + gem_exec_params$(EXEEXT) gem_exec_parse$(EXEEXT) \ + gem_fenced_exec_thrash$(EXEEXT) gem_fence_thrash$(EXEEXT) \ + gem_flink$(EXEEXT) gem_flink_race$(EXEEXT) \ + gem_linear_blits$(EXEEXT) gem_madvise$(EXEEXT) \ + gem_mmap$(EXEEXT) gem_mmap_gtt$(EXEEXT) \ + gem_partial_pwrite_pread$(EXEEXT) \ + gem_persistent_relocs$(EXEEXT) \ + gem_pipe_control_store_loop$(EXEEXT) gem_pread$(EXEEXT) \ + gem_pread_after_blit$(EXEEXT) gem_pwrite$(EXEEXT) \ + gem_pwrite_pread$(EXEEXT) gem_readwrite$(EXEEXT) \ + gem_reloc_overflow$(EXEEXT) gem_reloc_vs_gpu$(EXEEXT) \ + gem_reset_stats$(EXEEXT) gem_ringfill$(EXEEXT) \ + gem_set_tiling_vs_blt$(EXEEXT) \ + gem_storedw_batches_loop$(EXEEXT) gem_tiled_blits$(EXEEXT) \ + gem_tiled_partial_pwrite_pread$(EXEEXT) \ + gem_write_read_ring_switch$(EXEEXT) kms_addfb$(EXEEXT) \ + kms_cursor_crc$(EXEEXT) kms_fbc_crc$(EXEEXT) kms_flip$(EXEEXT) \ + kms_flip_tiling$(EXEEXT) kms_mmio_vs_cs_flip$(EXEEXT) \ + kms_pipe_crc_basic$(EXEEXT) kms_plane$(EXEEXT) \ + kms_render$(EXEEXT) kms_setmode$(EXEEXT) pm_lpsp$(EXEEXT) \ + pm_rpm$(EXEEXT) pm_rps$(EXEEXT) prime_self_import$(EXEEXT) \ + template$(EXEEXT) $(am__EXEEXT_3) +am__EXEEXT_5 = gem_bad_batch$(EXEEXT) gem_hang$(EXEEXT) \ + gem_bad_blit$(EXEEXT) gem_bad_address$(EXEEXT) \ + gem_non_secure_batch$(EXEEXT) +am__EXEEXT_6 = igt_no_exit$(EXEEXT) igt_no_exit_list_only$(EXEEXT) \ + igt_fork_helper$(EXEEXT) igt_list_only$(EXEEXT) \ + igt_no_subtest$(EXEEXT) igt_simulation$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +core_get_client_auth_SOURCES = core_get_client_auth.c +core_get_client_auth_OBJECTS = core_get_client_auth.$(OBJEXT) +core_get_client_auth_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +@BUILD_TESTS_TRUE@core_get_client_auth_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +core_getclient_SOURCES = core_getclient.c +core_getclient_OBJECTS = core_getclient.$(OBJEXT) +core_getclient_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@core_getclient_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +core_getstats_SOURCES = core_getstats.c +core_getstats_OBJECTS = core_getstats.$(OBJEXT) +core_getstats_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@core_getstats_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +core_getversion_SOURCES = core_getversion.c +core_getversion_OBJECTS = core_getversion.$(OBJEXT) +core_getversion_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@core_getversion_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +ddi_compute_wrpll_SOURCES = ddi_compute_wrpll.c +ddi_compute_wrpll_OBJECTS = ddi_compute_wrpll.$(OBJEXT) +ddi_compute_wrpll_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@ddi_compute_wrpll_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +drm_vma_limiter_SOURCES = drm_vma_limiter.c +drm_vma_limiter_OBJECTS = drm_vma_limiter.$(OBJEXT) +drm_vma_limiter_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@drm_vma_limiter_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +drm_vma_limiter_cached_SOURCES = drm_vma_limiter_cached.c +drm_vma_limiter_cached_OBJECTS = drm_vma_limiter_cached.$(OBJEXT) +drm_vma_limiter_cached_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@drm_vma_limiter_cached_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +drm_vma_limiter_cpu_SOURCES = drm_vma_limiter_cpu.c +drm_vma_limiter_cpu_OBJECTS = drm_vma_limiter_cpu.$(OBJEXT) +drm_vma_limiter_cpu_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@drm_vma_limiter_cpu_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +drm_vma_limiter_gtt_SOURCES = drm_vma_limiter_gtt.c +drm_vma_limiter_gtt_OBJECTS = drm_vma_limiter_gtt.$(OBJEXT) +drm_vma_limiter_gtt_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@drm_vma_limiter_gtt_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +drv_hangman_SOURCES = drv_hangman.c +drv_hangman_OBJECTS = drv_hangman.$(OBJEXT) +drv_hangman_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@drv_hangman_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +drv_suspend_SOURCES = drv_suspend.c +drv_suspend_OBJECTS = drv_suspend.$(OBJEXT) +drv_suspend_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@drv_suspend_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_alive_SOURCES = gem_alive.c +gem_alive_OBJECTS = gem_alive.$(OBJEXT) +gem_alive_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_alive_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_bad_address_SOURCES = gem_bad_address.c +gem_bad_address_OBJECTS = gem_bad_address.$(OBJEXT) +gem_bad_address_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_bad_address_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_bad_batch_SOURCES = gem_bad_batch.c +gem_bad_batch_OBJECTS = gem_bad_batch.$(OBJEXT) +gem_bad_batch_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_bad_batch_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_bad_blit_SOURCES = gem_bad_blit.c +gem_bad_blit_OBJECTS = gem_bad_blit.$(OBJEXT) +gem_bad_blit_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_bad_blit_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_bad_length_SOURCES = gem_bad_length.c +gem_bad_length_OBJECTS = gem_bad_length.$(OBJEXT) +gem_bad_length_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_bad_length_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_bad_reloc_SOURCES = gem_bad_reloc.c +gem_bad_reloc_OBJECTS = gem_bad_reloc.$(OBJEXT) +gem_bad_reloc_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_bad_reloc_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_basic_SOURCES = gem_basic.c +gem_basic_OBJECTS = gem_basic.$(OBJEXT) +gem_basic_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_basic_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_caching_SOURCES = gem_caching.c +gem_caching_OBJECTS = gem_caching.$(OBJEXT) +gem_caching_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_caching_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_close_race_SOURCES = gem_close_race.c +gem_close_race_OBJECTS = gem_close_race-gem_close_race.$(OBJEXT) +@BUILD_TESTS_TRUE@am__DEPENDENCIES_2 = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +@BUILD_TESTS_TRUE@gem_close_race_DEPENDENCIES = $(am__DEPENDENCIES_2) +gem_close_race_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(gem_close_race_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o \ + $@ +gem_concurrent_blit_SOURCES = gem_concurrent_blit.c +gem_concurrent_blit_OBJECTS = gem_concurrent_blit.$(OBJEXT) +gem_concurrent_blit_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_concurrent_blit_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_cpu_reloc_SOURCES = gem_cpu_reloc.c +gem_cpu_reloc_OBJECTS = gem_cpu_reloc.$(OBJEXT) +gem_cpu_reloc_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_cpu_reloc_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_cs_prefetch_SOURCES = gem_cs_prefetch.c +gem_cs_prefetch_OBJECTS = gem_cs_prefetch.$(OBJEXT) +gem_cs_prefetch_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_cs_prefetch_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_cs_tlb_SOURCES = gem_cs_tlb.c +gem_cs_tlb_OBJECTS = gem_cs_tlb.$(OBJEXT) +gem_cs_tlb_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_cs_tlb_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_ctx_bad_destroy_SOURCES = gem_ctx_bad_destroy.c +gem_ctx_bad_destroy_OBJECTS = gem_ctx_bad_destroy.$(OBJEXT) +gem_ctx_bad_destroy_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_ctx_bad_destroy_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_ctx_bad_exec_SOURCES = gem_ctx_bad_exec.c +gem_ctx_bad_exec_OBJECTS = gem_ctx_bad_exec.$(OBJEXT) +gem_ctx_bad_exec_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_ctx_bad_exec_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_ctx_basic_SOURCES = gem_ctx_basic.c +gem_ctx_basic_OBJECTS = gem_ctx_basic-gem_ctx_basic.$(OBJEXT) +@BUILD_TESTS_TRUE@gem_ctx_basic_DEPENDENCIES = $(am__DEPENDENCIES_2) +gem_ctx_basic_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(gem_ctx_basic_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +gem_ctx_create_SOURCES = gem_ctx_create.c +gem_ctx_create_OBJECTS = gem_ctx_create.$(OBJEXT) +gem_ctx_create_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_ctx_create_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_ctx_exec_SOURCES = gem_ctx_exec.c +gem_ctx_exec_OBJECTS = gem_ctx_exec.$(OBJEXT) +gem_ctx_exec_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_ctx_exec_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_double_irq_loop_SOURCES = gem_double_irq_loop.c +gem_double_irq_loop_OBJECTS = gem_double_irq_loop.$(OBJEXT) +gem_double_irq_loop_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_double_irq_loop_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_dummy_reloc_loop_SOURCES = gem_dummy_reloc_loop.c +gem_dummy_reloc_loop_OBJECTS = gem_dummy_reloc_loop.$(OBJEXT) +gem_dummy_reloc_loop_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_dummy_reloc_loop_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_evict_alignment_SOURCES = gem_evict_alignment.c +gem_evict_alignment_OBJECTS = gem_evict_alignment.$(OBJEXT) +gem_evict_alignment_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_evict_alignment_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_evict_everything_SOURCES = gem_evict_everything.c +gem_evict_everything_OBJECTS = gem_evict_everything.$(OBJEXT) +gem_evict_everything_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_evict_everything_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_exec_bad_domains_SOURCES = gem_exec_bad_domains.c +gem_exec_bad_domains_OBJECTS = gem_exec_bad_domains.$(OBJEXT) +gem_exec_bad_domains_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_exec_bad_domains_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_exec_big_SOURCES = gem_exec_big.c +gem_exec_big_OBJECTS = gem_exec_big.$(OBJEXT) +gem_exec_big_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_exec_big_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_exec_blt_SOURCES = gem_exec_blt.c +gem_exec_blt_OBJECTS = gem_exec_blt.$(OBJEXT) +gem_exec_blt_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_exec_blt_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_exec_faulting_reloc_SOURCES = gem_exec_faulting_reloc.c +gem_exec_faulting_reloc_OBJECTS = gem_exec_faulting_reloc.$(OBJEXT) +gem_exec_faulting_reloc_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_exec_faulting_reloc_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_exec_lut_handle_SOURCES = gem_exec_lut_handle.c +gem_exec_lut_handle_OBJECTS = gem_exec_lut_handle.$(OBJEXT) +gem_exec_lut_handle_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_exec_lut_handle_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_exec_nop_SOURCES = gem_exec_nop.c +gem_exec_nop_OBJECTS = gem_exec_nop.$(OBJEXT) +gem_exec_nop_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_exec_nop_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_exec_params_SOURCES = gem_exec_params.c +gem_exec_params_OBJECTS = gem_exec_params.$(OBJEXT) +gem_exec_params_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_exec_params_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_exec_parse_SOURCES = gem_exec_parse.c +gem_exec_parse_OBJECTS = gem_exec_parse.$(OBJEXT) +gem_exec_parse_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_exec_parse_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_fd_exhaustion_SOURCES = gem_fd_exhaustion.c +gem_fd_exhaustion_OBJECTS = gem_fd_exhaustion.$(OBJEXT) +gem_fd_exhaustion_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_fd_exhaustion_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_fence_thrash_SOURCES = gem_fence_thrash.c +gem_fence_thrash_OBJECTS = \ + gem_fence_thrash-gem_fence_thrash.$(OBJEXT) +@BUILD_TESTS_TRUE@gem_fence_thrash_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_2) +gem_fence_thrash_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(gem_fence_thrash_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +gem_fenced_exec_thrash_SOURCES = gem_fenced_exec_thrash.c +gem_fenced_exec_thrash_OBJECTS = gem_fenced_exec_thrash.$(OBJEXT) +gem_fenced_exec_thrash_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_fenced_exec_thrash_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_flink_SOURCES = gem_flink.c +gem_flink_OBJECTS = gem_flink.$(OBJEXT) +gem_flink_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_flink_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_flink_race_SOURCES = gem_flink_race.c +gem_flink_race_OBJECTS = gem_flink_race-gem_flink_race.$(OBJEXT) +@BUILD_TESTS_TRUE@gem_flink_race_DEPENDENCIES = $(am__DEPENDENCIES_2) +gem_flink_race_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(gem_flink_race_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o \ + $@ +gem_gtt_cpu_tlb_SOURCES = gem_gtt_cpu_tlb.c +gem_gtt_cpu_tlb_OBJECTS = gem_gtt_cpu_tlb.$(OBJEXT) +gem_gtt_cpu_tlb_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_gtt_cpu_tlb_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_gtt_hog_SOURCES = gem_gtt_hog.c +gem_gtt_hog_OBJECTS = gem_gtt_hog.$(OBJEXT) +gem_gtt_hog_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_gtt_hog_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_gtt_speed_SOURCES = gem_gtt_speed.c +gem_gtt_speed_OBJECTS = gem_gtt_speed.$(OBJEXT) +gem_gtt_speed_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_gtt_speed_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_hang_SOURCES = gem_hang.c +gem_hang_OBJECTS = gem_hang.$(OBJEXT) +gem_hang_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_hang_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_hangcheck_forcewake_SOURCES = gem_hangcheck_forcewake.c +gem_hangcheck_forcewake_OBJECTS = gem_hangcheck_forcewake.$(OBJEXT) +gem_hangcheck_forcewake_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_hangcheck_forcewake_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_largeobject_SOURCES = gem_largeobject.c +gem_largeobject_OBJECTS = gem_largeobject.$(OBJEXT) +gem_largeobject_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_largeobject_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_linear_blits_SOURCES = gem_linear_blits.c +gem_linear_blits_OBJECTS = gem_linear_blits.$(OBJEXT) +gem_linear_blits_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_linear_blits_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_lut_handle_SOURCES = gem_lut_handle.c +gem_lut_handle_OBJECTS = gem_lut_handle.$(OBJEXT) +gem_lut_handle_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_lut_handle_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_madvise_SOURCES = gem_madvise.c +gem_madvise_OBJECTS = gem_madvise.$(OBJEXT) +gem_madvise_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_madvise_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_media_fill_SOURCES = gem_media_fill.c +gem_media_fill_OBJECTS = gem_media_fill.$(OBJEXT) +gem_media_fill_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_media_fill_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_mmap_SOURCES = gem_mmap.c +gem_mmap_OBJECTS = gem_mmap.$(OBJEXT) +gem_mmap_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_mmap_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_mmap_gtt_SOURCES = gem_mmap_gtt.c +gem_mmap_gtt_OBJECTS = gem_mmap_gtt.$(OBJEXT) +gem_mmap_gtt_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_mmap_gtt_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_mmap_offset_exhaustion_SOURCES = gem_mmap_offset_exhaustion.c +gem_mmap_offset_exhaustion_OBJECTS = \ + gem_mmap_offset_exhaustion.$(OBJEXT) +gem_mmap_offset_exhaustion_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_mmap_offset_exhaustion_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_multi_bsd_sync_loop_SOURCES = gem_multi_bsd_sync_loop.c +gem_multi_bsd_sync_loop_OBJECTS = gem_multi_bsd_sync_loop.$(OBJEXT) +gem_multi_bsd_sync_loop_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_multi_bsd_sync_loop_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_non_secure_batch_SOURCES = gem_non_secure_batch.c +gem_non_secure_batch_OBJECTS = gem_non_secure_batch.$(OBJEXT) +gem_non_secure_batch_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_non_secure_batch_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_partial_pwrite_pread_SOURCES = gem_partial_pwrite_pread.c +gem_partial_pwrite_pread_OBJECTS = gem_partial_pwrite_pread.$(OBJEXT) +gem_partial_pwrite_pread_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_partial_pwrite_pread_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_persistent_relocs_SOURCES = gem_persistent_relocs.c +gem_persistent_relocs_OBJECTS = gem_persistent_relocs.$(OBJEXT) +gem_persistent_relocs_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_persistent_relocs_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_pin_SOURCES = gem_pin.c +gem_pin_OBJECTS = gem_pin.$(OBJEXT) +gem_pin_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_pin_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_pipe_control_store_loop_SOURCES = gem_pipe_control_store_loop.c +gem_pipe_control_store_loop_OBJECTS = \ + gem_pipe_control_store_loop.$(OBJEXT) +gem_pipe_control_store_loop_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_pipe_control_store_loop_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_pread_SOURCES = gem_pread.c +gem_pread_OBJECTS = gem_pread.$(OBJEXT) +gem_pread_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_pread_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_pread_after_blit_SOURCES = gem_pread_after_blit.c +gem_pread_after_blit_OBJECTS = gem_pread_after_blit.$(OBJEXT) +gem_pread_after_blit_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_pread_after_blit_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_pwrite_SOURCES = gem_pwrite.c +gem_pwrite_OBJECTS = gem_pwrite.$(OBJEXT) +gem_pwrite_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_pwrite_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_pwrite_pread_SOURCES = gem_pwrite_pread.c +gem_pwrite_pread_OBJECTS = gem_pwrite_pread.$(OBJEXT) +gem_pwrite_pread_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_pwrite_pread_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_readwrite_SOURCES = gem_readwrite.c +gem_readwrite_OBJECTS = gem_readwrite.$(OBJEXT) +gem_readwrite_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_readwrite_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_reg_read_SOURCES = gem_reg_read.c +gem_reg_read_OBJECTS = gem_reg_read.$(OBJEXT) +gem_reg_read_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_reg_read_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_reloc_overflow_SOURCES = gem_reloc_overflow.c +gem_reloc_overflow_OBJECTS = gem_reloc_overflow.$(OBJEXT) +gem_reloc_overflow_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_reloc_overflow_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_reloc_vs_gpu_SOURCES = gem_reloc_vs_gpu.c +gem_reloc_vs_gpu_OBJECTS = gem_reloc_vs_gpu.$(OBJEXT) +gem_reloc_vs_gpu_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_reloc_vs_gpu_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_render_copy_SOURCES = gem_render_copy.c +gem_render_copy_OBJECTS = gem_render_copy.$(OBJEXT) +gem_render_copy_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_render_copy_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_render_copy_redux_SOURCES = gem_render_copy_redux.c +gem_render_copy_redux_OBJECTS = gem_render_copy_redux.$(OBJEXT) +gem_render_copy_redux_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_render_copy_redux_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_render_linear_blits_SOURCES = gem_render_linear_blits.c +gem_render_linear_blits_OBJECTS = gem_render_linear_blits.$(OBJEXT) +gem_render_linear_blits_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_render_linear_blits_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_render_tiled_blits_SOURCES = gem_render_tiled_blits.c +gem_render_tiled_blits_OBJECTS = gem_render_tiled_blits.$(OBJEXT) +gem_render_tiled_blits_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_render_tiled_blits_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_reset_stats_SOURCES = gem_reset_stats.c +gem_reset_stats_OBJECTS = gem_reset_stats.$(OBJEXT) +gem_reset_stats_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_reset_stats_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_ring_sync_copy_SOURCES = gem_ring_sync_copy.c +gem_ring_sync_copy_OBJECTS = gem_ring_sync_copy.$(OBJEXT) +gem_ring_sync_copy_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_ring_sync_copy_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_ring_sync_loop_SOURCES = gem_ring_sync_loop.c +gem_ring_sync_loop_OBJECTS = gem_ring_sync_loop.$(OBJEXT) +gem_ring_sync_loop_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_ring_sync_loop_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_ringfill_SOURCES = gem_ringfill.c +gem_ringfill_OBJECTS = gem_ringfill.$(OBJEXT) +gem_ringfill_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_ringfill_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_seqno_wrap_SOURCES = gem_seqno_wrap.c +gem_seqno_wrap_OBJECTS = gem_seqno_wrap.$(OBJEXT) +gem_seqno_wrap_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_seqno_wrap_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_set_tiling_vs_blt_SOURCES = gem_set_tiling_vs_blt.c +gem_set_tiling_vs_blt_OBJECTS = gem_set_tiling_vs_blt.$(OBJEXT) +gem_set_tiling_vs_blt_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_set_tiling_vs_blt_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_set_tiling_vs_gtt_SOURCES = gem_set_tiling_vs_gtt.c +gem_set_tiling_vs_gtt_OBJECTS = gem_set_tiling_vs_gtt.$(OBJEXT) +gem_set_tiling_vs_gtt_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_set_tiling_vs_gtt_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_set_tiling_vs_pwrite_SOURCES = gem_set_tiling_vs_pwrite.c +gem_set_tiling_vs_pwrite_OBJECTS = gem_set_tiling_vs_pwrite.$(OBJEXT) +gem_set_tiling_vs_pwrite_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_set_tiling_vs_pwrite_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_storedw_batches_loop_SOURCES = gem_storedw_batches_loop.c +gem_storedw_batches_loop_OBJECTS = gem_storedw_batches_loop.$(OBJEXT) +gem_storedw_batches_loop_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_storedw_batches_loop_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_storedw_loop_blt_SOURCES = gem_storedw_loop_blt.c +gem_storedw_loop_blt_OBJECTS = gem_storedw_loop_blt.$(OBJEXT) +gem_storedw_loop_blt_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_storedw_loop_blt_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_storedw_loop_bsd_SOURCES = gem_storedw_loop_bsd.c +gem_storedw_loop_bsd_OBJECTS = gem_storedw_loop_bsd.$(OBJEXT) +gem_storedw_loop_bsd_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_storedw_loop_bsd_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_storedw_loop_render_SOURCES = gem_storedw_loop_render.c +gem_storedw_loop_render_OBJECTS = gem_storedw_loop_render.$(OBJEXT) +gem_storedw_loop_render_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_storedw_loop_render_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_storedw_loop_vebox_SOURCES = gem_storedw_loop_vebox.c +gem_storedw_loop_vebox_OBJECTS = gem_storedw_loop_vebox.$(OBJEXT) +gem_storedw_loop_vebox_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_storedw_loop_vebox_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_stress_SOURCES = gem_stress.c +gem_stress_OBJECTS = gem_stress.$(OBJEXT) +gem_stress_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_stress_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_threaded_access_tiled_SOURCES = gem_threaded_access_tiled.c +gem_threaded_access_tiled_OBJECTS = \ + gem_threaded_access_tiled-gem_threaded_access_tiled.$(OBJEXT) +@BUILD_TESTS_TRUE@gem_threaded_access_tiled_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_2) +gem_threaded_access_tiled_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(gem_threaded_access_tiled_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +gem_tiled_blits_SOURCES = gem_tiled_blits.c +gem_tiled_blits_OBJECTS = gem_tiled_blits.$(OBJEXT) +gem_tiled_blits_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_tiled_blits_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_tiled_fence_blits_SOURCES = gem_tiled_fence_blits.c +gem_tiled_fence_blits_OBJECTS = gem_tiled_fence_blits.$(OBJEXT) +gem_tiled_fence_blits_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_tiled_fence_blits_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_tiled_partial_pwrite_pread_SOURCES = \ + gem_tiled_partial_pwrite_pread.c +gem_tiled_partial_pwrite_pread_OBJECTS = \ + gem_tiled_partial_pwrite_pread.$(OBJEXT) +gem_tiled_partial_pwrite_pread_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_tiled_partial_pwrite_pread_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_tiled_pread_SOURCES = gem_tiled_pread.c +gem_tiled_pread_OBJECTS = gem_tiled_pread.$(OBJEXT) +gem_tiled_pread_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_tiled_pread_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_tiled_pread_pwrite_SOURCES = gem_tiled_pread_pwrite.c +gem_tiled_pread_pwrite_OBJECTS = gem_tiled_pread_pwrite.$(OBJEXT) +gem_tiled_pread_pwrite_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_tiled_pread_pwrite_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_tiled_swapping_SOURCES = gem_tiled_swapping.c +gem_tiled_swapping_OBJECTS = \ + gem_tiled_swapping-gem_tiled_swapping.$(OBJEXT) +@BUILD_TESTS_TRUE@gem_tiled_swapping_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_2) +gem_tiled_swapping_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(gem_tiled_swapping_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +gem_tiling_max_stride_SOURCES = gem_tiling_max_stride.c +gem_tiling_max_stride_OBJECTS = gem_tiling_max_stride.$(OBJEXT) +gem_tiling_max_stride_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_tiling_max_stride_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_unfence_active_buffers_SOURCES = gem_unfence_active_buffers.c +gem_unfence_active_buffers_OBJECTS = \ + gem_unfence_active_buffers.$(OBJEXT) +gem_unfence_active_buffers_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_unfence_active_buffers_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_unref_active_buffers_SOURCES = gem_unref_active_buffers.c +gem_unref_active_buffers_OBJECTS = gem_unref_active_buffers.$(OBJEXT) +gem_unref_active_buffers_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_unref_active_buffers_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_userptr_blits_SOURCES = gem_userptr_blits.c +gem_userptr_blits_OBJECTS = gem_userptr_blits.$(OBJEXT) +gem_userptr_blits_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_userptr_blits_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gem_wait_render_timeout_SOURCES = gem_wait_render_timeout.c +gem_wait_render_timeout_OBJECTS = gem_wait_render_timeout.$(OBJEXT) +@BUILD_TESTS_TRUE@gem_wait_render_timeout_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_2) +gem_write_read_ring_switch_SOURCES = gem_write_read_ring_switch.c +gem_write_read_ring_switch_OBJECTS = \ + gem_write_read_ring_switch.$(OBJEXT) +gem_write_read_ring_switch_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gem_write_read_ring_switch_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gen3_mixed_blits_SOURCES = gen3_mixed_blits.c +gen3_mixed_blits_OBJECTS = gen3_mixed_blits.$(OBJEXT) +gen3_mixed_blits_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gen3_mixed_blits_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gen3_render_linear_blits_SOURCES = gen3_render_linear_blits.c +gen3_render_linear_blits_OBJECTS = gen3_render_linear_blits.$(OBJEXT) +gen3_render_linear_blits_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gen3_render_linear_blits_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gen3_render_mixed_blits_SOURCES = gen3_render_mixed_blits.c +gen3_render_mixed_blits_OBJECTS = gen3_render_mixed_blits.$(OBJEXT) +gen3_render_mixed_blits_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gen3_render_mixed_blits_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gen3_render_tiledx_blits_SOURCES = gen3_render_tiledx_blits.c +gen3_render_tiledx_blits_OBJECTS = gen3_render_tiledx_blits.$(OBJEXT) +gen3_render_tiledx_blits_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gen3_render_tiledx_blits_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gen3_render_tiledy_blits_SOURCES = gen3_render_tiledy_blits.c +gen3_render_tiledy_blits_OBJECTS = gen3_render_tiledy_blits.$(OBJEXT) +gen3_render_tiledy_blits_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@gen3_render_tiledy_blits_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +gen7_forcewake_mt_SOURCES = gen7_forcewake_mt.c +gen7_forcewake_mt_OBJECTS = \ + gen7_forcewake_mt-gen7_forcewake_mt.$(OBJEXT) +@BUILD_TESTS_TRUE@gen7_forcewake_mt_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_2) +gen7_forcewake_mt_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(gen7_forcewake_mt_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +igt_fork_helper_SOURCES = igt_fork_helper.c +igt_fork_helper_OBJECTS = igt_fork_helper.$(OBJEXT) +igt_fork_helper_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@igt_fork_helper_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +igt_list_only_SOURCES = igt_list_only.c +igt_list_only_OBJECTS = igt_list_only.$(OBJEXT) +igt_list_only_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@igt_list_only_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +igt_no_exit_SOURCES = igt_no_exit.c +igt_no_exit_OBJECTS = igt_no_exit.$(OBJEXT) +igt_no_exit_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@igt_no_exit_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +igt_no_exit_list_only_SOURCES = igt_no_exit_list_only.c +igt_no_exit_list_only_OBJECTS = igt_no_exit_list_only.$(OBJEXT) +igt_no_exit_list_only_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@igt_no_exit_list_only_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +igt_no_subtest_SOURCES = igt_no_subtest.c +igt_no_subtest_OBJECTS = igt_no_subtest.$(OBJEXT) +igt_no_subtest_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@igt_no_subtest_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +igt_simulation_SOURCES = igt_simulation.c +igt_simulation_OBJECTS = igt_simulation.$(OBJEXT) +igt_simulation_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@igt_simulation_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +kms_addfb_SOURCES = kms_addfb.c +kms_addfb_OBJECTS = kms_addfb.$(OBJEXT) +kms_addfb_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@kms_addfb_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +kms_cursor_crc_SOURCES = kms_cursor_crc.c +kms_cursor_crc_OBJECTS = kms_cursor_crc.$(OBJEXT) +kms_cursor_crc_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@kms_cursor_crc_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +kms_fbc_crc_SOURCES = kms_fbc_crc.c +kms_fbc_crc_OBJECTS = kms_fbc_crc.$(OBJEXT) +kms_fbc_crc_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@kms_fbc_crc_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +kms_fence_pin_leak_SOURCES = kms_fence_pin_leak.c +kms_fence_pin_leak_OBJECTS = kms_fence_pin_leak.$(OBJEXT) +kms_fence_pin_leak_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@kms_fence_pin_leak_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +kms_flip_SOURCES = kms_flip.c +kms_flip_OBJECTS = kms_flip.$(OBJEXT) +@BUILD_TESTS_TRUE@kms_flip_DEPENDENCIES = $(am__DEPENDENCIES_2) +kms_flip_tiling_SOURCES = kms_flip_tiling.c +kms_flip_tiling_OBJECTS = kms_flip_tiling.$(OBJEXT) +kms_flip_tiling_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@kms_flip_tiling_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +kms_mmio_vs_cs_flip_SOURCES = kms_mmio_vs_cs_flip.c +kms_mmio_vs_cs_flip_OBJECTS = kms_mmio_vs_cs_flip.$(OBJEXT) +kms_mmio_vs_cs_flip_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@kms_mmio_vs_cs_flip_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +kms_pipe_crc_basic_SOURCES = kms_pipe_crc_basic.c +kms_pipe_crc_basic_OBJECTS = kms_pipe_crc_basic.$(OBJEXT) +kms_pipe_crc_basic_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@kms_pipe_crc_basic_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +kms_plane_SOURCES = kms_plane.c +kms_plane_OBJECTS = kms_plane.$(OBJEXT) +kms_plane_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@kms_plane_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +kms_render_SOURCES = kms_render.c +kms_render_OBJECTS = kms_render.$(OBJEXT) +kms_render_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@kms_render_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +kms_setmode_SOURCES = kms_setmode.c +kms_setmode_OBJECTS = kms_setmode.$(OBJEXT) +kms_setmode_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@kms_setmode_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +kms_sink_crc_basic_SOURCES = kms_sink_crc_basic.c +kms_sink_crc_basic_OBJECTS = kms_sink_crc_basic.$(OBJEXT) +kms_sink_crc_basic_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@kms_sink_crc_basic_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +pm_lpsp_SOURCES = pm_lpsp.c +pm_lpsp_OBJECTS = pm_lpsp.$(OBJEXT) +pm_lpsp_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@pm_lpsp_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +pm_psr_SOURCES = pm_psr.c +pm_psr_OBJECTS = pm_psr.$(OBJEXT) +pm_psr_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@pm_psr_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +pm_rc6_residency_SOURCES = pm_rc6_residency.c +pm_rc6_residency_OBJECTS = pm_rc6_residency.$(OBJEXT) +pm_rc6_residency_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@pm_rc6_residency_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +pm_rpm_SOURCES = pm_rpm.c +pm_rpm_OBJECTS = pm_rpm.$(OBJEXT) +pm_rpm_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@pm_rpm_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +pm_rps_SOURCES = pm_rps.c +pm_rps_OBJECTS = pm_rps.$(OBJEXT) +pm_rps_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@pm_rps_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +prime_nv_api_SOURCES = prime_nv_api.c +prime_nv_api_OBJECTS = prime_nv_api-prime_nv_api.$(OBJEXT) +@BUILD_TESTS_TRUE@prime_nv_api_DEPENDENCIES = $(am__DEPENDENCIES_2) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +prime_nv_api_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(prime_nv_api_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +prime_nv_pcopy_SOURCES = prime_nv_pcopy.c +prime_nv_pcopy_OBJECTS = prime_nv_pcopy-prime_nv_pcopy.$(OBJEXT) +@BUILD_TESTS_TRUE@prime_nv_pcopy_DEPENDENCIES = $(am__DEPENDENCIES_2) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +prime_nv_pcopy_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(prime_nv_pcopy_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o \ + $@ +prime_nv_test_SOURCES = prime_nv_test.c +prime_nv_test_OBJECTS = prime_nv_test-prime_nv_test.$(OBJEXT) +@BUILD_TESTS_TRUE@prime_nv_test_DEPENDENCIES = $(am__DEPENDENCIES_2) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +prime_nv_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(prime_nv_test_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +prime_self_import_SOURCES = prime_self_import.c +prime_self_import_OBJECTS = \ + prime_self_import-prime_self_import.$(OBJEXT) +@BUILD_TESTS_TRUE@prime_self_import_DEPENDENCIES = \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_2) +prime_self_import_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(prime_self_import_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +prime_udl_SOURCES = prime_udl.c +prime_udl_OBJECTS = prime_udl.$(OBJEXT) +prime_udl_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@prime_udl_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +template_SOURCES = template.c +template_OBJECTS = template.$(OBJEXT) +template_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@template_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +am_testdisplay_OBJECTS = testdisplay.$(OBJEXT) \ + testdisplay_hotplug.$(OBJEXT) +testdisplay_OBJECTS = $(am_testdisplay_OBJECTS) +testdisplay_LDADD = $(LDADD) +@BUILD_TESTS_TRUE@testdisplay_DEPENDENCIES = ../lib/libintel_tools.la \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@BUILD_TESTS_TRUE@ $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = core_get_client_auth.c core_getclient.c core_getstats.c \ + core_getversion.c ddi_compute_wrpll.c drm_vma_limiter.c \ + drm_vma_limiter_cached.c drm_vma_limiter_cpu.c \ + drm_vma_limiter_gtt.c drv_hangman.c drv_suspend.c gem_alive.c \ + gem_bad_address.c gem_bad_batch.c gem_bad_blit.c \ + gem_bad_length.c gem_bad_reloc.c gem_basic.c gem_caching.c \ + gem_close_race.c gem_concurrent_blit.c gem_cpu_reloc.c \ + gem_cs_prefetch.c gem_cs_tlb.c gem_ctx_bad_destroy.c \ + gem_ctx_bad_exec.c gem_ctx_basic.c gem_ctx_create.c \ + gem_ctx_exec.c gem_double_irq_loop.c gem_dummy_reloc_loop.c \ + gem_evict_alignment.c gem_evict_everything.c \ + gem_exec_bad_domains.c gem_exec_big.c gem_exec_blt.c \ + gem_exec_faulting_reloc.c gem_exec_lut_handle.c gem_exec_nop.c \ + gem_exec_params.c gem_exec_parse.c gem_fd_exhaustion.c \ + gem_fence_thrash.c gem_fenced_exec_thrash.c gem_flink.c \ + gem_flink_race.c gem_gtt_cpu_tlb.c gem_gtt_hog.c \ + gem_gtt_speed.c gem_hang.c gem_hangcheck_forcewake.c \ + gem_largeobject.c gem_linear_blits.c gem_lut_handle.c \ + gem_madvise.c gem_media_fill.c gem_mmap.c gem_mmap_gtt.c \ + gem_mmap_offset_exhaustion.c gem_multi_bsd_sync_loop.c \ + gem_non_secure_batch.c gem_partial_pwrite_pread.c \ + gem_persistent_relocs.c gem_pin.c \ + gem_pipe_control_store_loop.c gem_pread.c \ + gem_pread_after_blit.c gem_pwrite.c gem_pwrite_pread.c \ + gem_readwrite.c gem_reg_read.c gem_reloc_overflow.c \ + gem_reloc_vs_gpu.c gem_render_copy.c gem_render_copy_redux.c \ + gem_render_linear_blits.c gem_render_tiled_blits.c \ + gem_reset_stats.c gem_ring_sync_copy.c gem_ring_sync_loop.c \ + gem_ringfill.c gem_seqno_wrap.c gem_set_tiling_vs_blt.c \ + gem_set_tiling_vs_gtt.c gem_set_tiling_vs_pwrite.c \ + gem_storedw_batches_loop.c gem_storedw_loop_blt.c \ + gem_storedw_loop_bsd.c gem_storedw_loop_render.c \ + gem_storedw_loop_vebox.c gem_stress.c \ + gem_threaded_access_tiled.c gem_tiled_blits.c \ + gem_tiled_fence_blits.c gem_tiled_partial_pwrite_pread.c \ + gem_tiled_pread.c gem_tiled_pread_pwrite.c \ + gem_tiled_swapping.c gem_tiling_max_stride.c \ + gem_unfence_active_buffers.c gem_unref_active_buffers.c \ + gem_userptr_blits.c gem_wait_render_timeout.c \ + gem_write_read_ring_switch.c gen3_mixed_blits.c \ + gen3_render_linear_blits.c gen3_render_mixed_blits.c \ + gen3_render_tiledx_blits.c gen3_render_tiledy_blits.c \ + gen7_forcewake_mt.c igt_fork_helper.c igt_list_only.c \ + igt_no_exit.c igt_no_exit_list_only.c igt_no_subtest.c \ + igt_simulation.c kms_addfb.c kms_cursor_crc.c kms_fbc_crc.c \ + kms_fence_pin_leak.c kms_flip.c kms_flip_tiling.c \ + kms_mmio_vs_cs_flip.c kms_pipe_crc_basic.c kms_plane.c \ + kms_render.c kms_setmode.c kms_sink_crc_basic.c pm_lpsp.c \ + pm_psr.c pm_rc6_residency.c pm_rpm.c pm_rps.c prime_nv_api.c \ + prime_nv_pcopy.c prime_nv_test.c prime_self_import.c \ + prime_udl.c template.c $(testdisplay_SOURCES) +DIST_SOURCES = core_get_client_auth.c core_getclient.c core_getstats.c \ + core_getversion.c ddi_compute_wrpll.c drm_vma_limiter.c \ + drm_vma_limiter_cached.c drm_vma_limiter_cpu.c \ + drm_vma_limiter_gtt.c drv_hangman.c drv_suspend.c gem_alive.c \ + gem_bad_address.c gem_bad_batch.c gem_bad_blit.c \ + gem_bad_length.c gem_bad_reloc.c gem_basic.c gem_caching.c \ + gem_close_race.c gem_concurrent_blit.c gem_cpu_reloc.c \ + gem_cs_prefetch.c gem_cs_tlb.c gem_ctx_bad_destroy.c \ + gem_ctx_bad_exec.c gem_ctx_basic.c gem_ctx_create.c \ + gem_ctx_exec.c gem_double_irq_loop.c gem_dummy_reloc_loop.c \ + gem_evict_alignment.c gem_evict_everything.c \ + gem_exec_bad_domains.c gem_exec_big.c gem_exec_blt.c \ + gem_exec_faulting_reloc.c gem_exec_lut_handle.c gem_exec_nop.c \ + gem_exec_params.c gem_exec_parse.c gem_fd_exhaustion.c \ + gem_fence_thrash.c gem_fenced_exec_thrash.c gem_flink.c \ + gem_flink_race.c gem_gtt_cpu_tlb.c gem_gtt_hog.c \ + gem_gtt_speed.c gem_hang.c gem_hangcheck_forcewake.c \ + gem_largeobject.c gem_linear_blits.c gem_lut_handle.c \ + gem_madvise.c gem_media_fill.c gem_mmap.c gem_mmap_gtt.c \ + gem_mmap_offset_exhaustion.c gem_multi_bsd_sync_loop.c \ + gem_non_secure_batch.c gem_partial_pwrite_pread.c \ + gem_persistent_relocs.c gem_pin.c \ + gem_pipe_control_store_loop.c gem_pread.c \ + gem_pread_after_blit.c gem_pwrite.c gem_pwrite_pread.c \ + gem_readwrite.c gem_reg_read.c gem_reloc_overflow.c \ + gem_reloc_vs_gpu.c gem_render_copy.c gem_render_copy_redux.c \ + gem_render_linear_blits.c gem_render_tiled_blits.c \ + gem_reset_stats.c gem_ring_sync_copy.c gem_ring_sync_loop.c \ + gem_ringfill.c gem_seqno_wrap.c gem_set_tiling_vs_blt.c \ + gem_set_tiling_vs_gtt.c gem_set_tiling_vs_pwrite.c \ + gem_storedw_batches_loop.c gem_storedw_loop_blt.c \ + gem_storedw_loop_bsd.c gem_storedw_loop_render.c \ + gem_storedw_loop_vebox.c gem_stress.c \ + gem_threaded_access_tiled.c gem_tiled_blits.c \ + gem_tiled_fence_blits.c gem_tiled_partial_pwrite_pread.c \ + gem_tiled_pread.c gem_tiled_pread_pwrite.c \ + gem_tiled_swapping.c gem_tiling_max_stride.c \ + gem_unfence_active_buffers.c gem_unref_active_buffers.c \ + gem_userptr_blits.c gem_wait_render_timeout.c \ + gem_write_read_ring_switch.c gen3_mixed_blits.c \ + gen3_render_linear_blits.c gen3_render_mixed_blits.c \ + gen3_render_tiledx_blits.c gen3_render_tiledy_blits.c \ + gen7_forcewake_mt.c igt_fork_helper.c igt_list_only.c \ + igt_no_exit.c igt_no_exit_list_only.c igt_no_subtest.c \ + igt_simulation.c kms_addfb.c kms_cursor_crc.c kms_fbc_crc.c \ + kms_fence_pin_leak.c kms_flip.c kms_flip_tiling.c \ + kms_mmio_vs_cs_flip.c kms_pipe_crc_basic.c kms_plane.c \ + kms_render.c kms_setmode.c kms_sink_crc_basic.c pm_lpsp.c \ + pm_psr.c pm_rc6_residency.c pm_rpm.c pm_rps.c prime_nv_api.c \ + prime_nv_pcopy.c prime_nv_test.c prime_self_import.c \ + prime_udl.c template.c $(testdisplay_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ADMIN_MAN_DIR = @ADMIN_MAN_DIR@ +ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APP_MAN_DIR = @APP_MAN_DIR@ +APP_MAN_SUFFIX = @APP_MAN_SUFFIX@ +AR = @AR@ +ASSEMBLER_WARN_CFLAGS = @ASSEMBLER_WARN_CFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +AX_SWIG_PYTHON_CPPFLAGS = @AX_SWIG_PYTHON_CPPFLAGS@ +AX_SWIG_PYTHON_OPT = @AX_SWIG_PYTHON_OPT@ +BASE_CFLAGS = @BASE_CFLAGS@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHANGELOG_CMD = @CHANGELOG_CMD@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CWARNFLAGS = @CWARNFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DRI2PROTO_CFLAGS = @DRI2PROTO_CFLAGS@ +DRI2PROTO_LIBS = @DRI2PROTO_LIBS@ +DRIVER_MAN_DIR = @DRIVER_MAN_DIR@ +DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@ +DRM_CFLAGS = @DRM_CFLAGS@ +DRM_LIBS = @DRM_LIBS@ +DRM_NOUVEAU_CFLAGS = @DRM_NOUVEAU_CFLAGS@ +DRM_NOUVEAU_LIBS = @DRM_NOUVEAU_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILE_MAN_DIR = @FILE_MAN_DIR@ +FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_LIBS = @GLIB_LIBS@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_CMD = @INSTALL_CMD@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUDEV_CFLAGS = @LIBUDEV_CFLAGS@ +LIBUDEV_LIBS = @LIBUDEV_LIBS@ +LIB_MAN_DIR = @LIB_MAN_DIR@ +LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAN_SUBSTS = @MAN_SUBSTS@ +MISC_MAN_DIR = @MISC_MAN_DIR@ +MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJCOPY = @OBJCOPY@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERLAY_XLIB_CFLAGS = @OVERLAY_XLIB_CFLAGS@ +OVERLAY_XLIB_LIBS = @OVERLAY_XLIB_LIBS@ +OVERLAY_XVLIB_CFLAGS = @OVERLAY_XVLIB_CFLAGS@ +OVERLAY_XVLIB_LIBS = @OVERLAY_XVLIB_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PCIACCESS_CFLAGS = @PCIACCESS_CFLAGS@ +PCIACCESS_LIBS = @PCIACCESS_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PYTHON = @PYTHON@ +PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@ +PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ +PYTHON_LDFLAGS = @PYTHON_LDFLAGS@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRICT_CFLAGS = @STRICT_CFLAGS@ +STRIP = @STRIP@ +SWIG = @SWIG@ +SWIG_LIB = @SWIG_LIB@ +THREAD_CFLAGS = @THREAD_CFLAGS@ +VERSION = @VERSION@ +XORG_MAN_PAGE = @XORG_MAN_PAGE@ +XRANDR_CFLAGS = @XRANDR_CFLAGS@ +XRANDR_LIBS = @XRANDR_LIBS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NOUVEAU_TESTS_M = \ + prime_nv_api \ + prime_nv_pcopy \ + prime_nv_test \ + $(NULL) + +TESTS_progs_M = core_get_client_auth drv_suspend drv_hangman \ + gem_bad_reloc gem_basic gem_caching gem_close_race \ + gem_concurrent_blit gem_cs_tlb gem_ctx_bad_exec gem_ctx_exec \ + gem_dummy_reloc_loop gem_evict_alignment gem_evict_everything \ + gem_exec_bad_domains gem_exec_faulting_reloc gem_exec_nop \ + gem_exec_params gem_exec_parse gem_fenced_exec_thrash \ + gem_fence_thrash gem_flink gem_flink_race gem_linear_blits \ + gem_madvise gem_mmap gem_mmap_gtt gem_partial_pwrite_pread \ + gem_persistent_relocs gem_pipe_control_store_loop gem_pread \ + gem_pread_after_blit gem_pwrite gem_pwrite_pread gem_readwrite \ + gem_reloc_overflow gem_reloc_vs_gpu gem_reset_stats \ + gem_ringfill gem_set_tiling_vs_blt gem_storedw_batches_loop \ + gem_tiled_blits gem_tiled_partial_pwrite_pread \ + gem_write_read_ring_switch kms_addfb kms_cursor_crc \ + kms_fbc_crc kms_flip kms_flip_tiling kms_mmio_vs_cs_flip \ + kms_pipe_crc_basic kms_plane kms_render kms_setmode pm_lpsp \ + pm_rpm pm_rps prime_self_import template $(NULL) \ + $(am__append_1) +TESTS_progs = core_getclient core_getstats core_getversion \ + drm_vma_limiter drm_vma_limiter_cached drm_vma_limiter_cpu \ + drm_vma_limiter_gtt gem_bad_length gem_cpu_reloc \ + gem_cs_prefetch gem_ctx_bad_destroy gem_ctx_basic \ + gem_ctx_create gem_double_irq_loop gem_exec_big gem_exec_blt \ + gem_exec_lut_handle gem_fd_exhaustion gem_gtt_cpu_tlb \ + gem_gtt_hog gem_gtt_speed gem_hangcheck_forcewake \ + gem_largeobject gem_lut_handle gem_mmap_offset_exhaustion \ + gem_media_fill gem_pin gem_reg_read gem_render_copy \ + gem_render_copy_redux gem_render_linear_blits \ + gem_render_tiled_blits gem_ring_sync_copy gem_ring_sync_loop \ + gem_multi_bsd_sync_loop gem_seqno_wrap gem_set_tiling_vs_gtt \ + gem_set_tiling_vs_pwrite gem_storedw_loop_blt \ + gem_storedw_loop_bsd gem_storedw_loop_render \ + gem_storedw_loop_vebox gem_threaded_access_tiled \ + gem_tiled_fence_blits gem_tiled_pread gem_tiled_pread_pwrite \ + gem_tiled_swapping gem_tiling_max_stride \ + gem_unfence_active_buffers gem_unref_active_buffers \ + gem_userptr_blits gem_wait_render_timeout gen3_mixed_blits \ + gen3_render_linear_blits gen3_render_mixed_blits \ + gen3_render_tiledx_blits gen3_render_tiledy_blits \ + gen7_forcewake_mt kms_sink_crc_basic kms_fence_pin_leak pm_psr \ + pm_rc6_residency prime_udl $(NULL) testdisplay + +# IMPORTANT: The ZZ_ tests need to be run last! +# ... and make can't deal with inlined comments ... +TESTS_scripts_M = \ + $(NULL) + +TESTS_scripts = \ + debugfs_emon_crash \ + drv_debugfs_reader \ + drv_missed_irq_hang \ + drv_module_reload \ + kms_sysfs_edid_timing \ + sysfs_l3_parity \ + test_rte_check \ + tools_test \ + $(NULL) + + +# This target contains testcases which support automagic subtest enumeration +# from the piglit testrunner with --list-subtests and running individual +# subtests with --run-subtest <testname> +# +# Your testcase should probably use an igt_main and igt_fixture and should have +# a pile of igt_subtest blocks. +multi_kernel_tests = \ + $(TESTS_progs_M) \ + $(TESTS_scripts_M) \ + $(NULL) + + +# This target is for simple testcase which don't expose any subtest. +# +# Your testcase should probably use igt_simple_main, but none of the other magic +# blocks like igt_fixture or igt_subtest. +single_kernel_tests = \ + $(TESTS_progs) \ + $(TESTS_scripts) \ + $(NULL) + +kernel_tests = \ + $(single_kernel_tests) \ + $(multi_kernel_tests) \ + $(NULL) + +TESTS_testsuite = \ + igt_no_exit \ + igt_no_exit_list_only \ + igt_fork_helper \ + igt_list_only \ + igt_no_subtest \ + igt_simulation \ + $(NULL) + + +# IMPORTANT: These tests here are all disabled because the result in sometime +# unrecoverable gpu hangs. Don't put real testcases here. +HANG = \ + gem_bad_batch \ + gem_hang \ + gem_bad_blit \ + gem_bad_address \ + gem_non_secure_batch \ + $(NULL) + +scripts = \ + check_drm_clients \ + ddx_intel_after_fbdev \ + debugfs_wedged \ + drm_lib.sh \ + $(NULL) + +IMAGES = pass.png 1080p-left.png 1080p-right.png +testdisplay_SOURCES = \ + testdisplay.c \ + testdisplay.h \ + testdisplay_hotplug.c \ + $(NULL) + +common_files = \ + eviction_common.c \ + $(NULL) + +@BUILD_TESTS_TRUE@EXTRA_DIST = $(TESTS_scripts) $(TESTS_scripts_M) $(scripts) $(IMAGES) $(common_files) +@BUILD_TESTS_TRUE@CLEANFILES = $(EXTRA_PROGRAMS) single-tests.txt multi-tests.txt +@BUILD_TESTS_TRUE@AM_CFLAGS = $(DRM_CFLAGS) $(CWARNFLAGS) \ +@BUILD_TESTS_TRUE@ -I$(srcdir)/.. -I$(srcdir)/../lib -include \ +@BUILD_TESTS_TRUE@ "$(srcdir)/../lib/check-ndebug.h" -include \ +@BUILD_TESTS_TRUE@ "$(top_builddir)/version.h" \ +@BUILD_TESTS_TRUE@ -DIGT_DATADIR=\""$(abs_srcdir)"\" $(NULL) \ +@BUILD_TESTS_TRUE@ $(CAIRO_CFLAGS) $(LIBUDEV_CFLAGS) \ +@BUILD_TESTS_TRUE@ $(GLIB_CFLAGS) +@BUILD_TESTS_TRUE@LDADD = ../lib/libintel_tools.la $(PCIACCESS_LIBS) \ +@BUILD_TESTS_TRUE@ $(DRM_LIBS) $(CAIRO_LIBS) $(LIBUDEV_LIBS) \ +@BUILD_TESTS_TRUE@ $(GLIB_LIBS) +@BUILD_TESTS_TRUE@gem_close_race_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) +@BUILD_TESTS_TRUE@gem_close_race_LDADD = $(LDADD) -lpthread +@BUILD_TESTS_TRUE@gem_ctx_basic_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) +@BUILD_TESTS_TRUE@gem_ctx_basic_LDADD = $(LDADD) -lpthread +@BUILD_TESTS_TRUE@gem_fence_thrash_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) +@BUILD_TESTS_TRUE@gem_fence_thrash_LDADD = $(LDADD) -lpthread +@BUILD_TESTS_TRUE@gem_flink_race_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) +@BUILD_TESTS_TRUE@gem_flink_race_LDADD = $(LDADD) -lpthread +@BUILD_TESTS_TRUE@gem_threaded_access_tiled_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) +@BUILD_TESTS_TRUE@gem_threaded_access_tiled_LDADD = $(LDADD) -lpthread +@BUILD_TESTS_TRUE@gem_tiled_swapping_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) +@BUILD_TESTS_TRUE@gem_tiled_swapping_LDADD = $(LDADD) -lpthread +@BUILD_TESTS_TRUE@prime_self_import_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) +@BUILD_TESTS_TRUE@prime_self_import_LDADD = $(LDADD) -lpthread +@BUILD_TESTS_TRUE@gen7_forcewake_mt_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) +@BUILD_TESTS_TRUE@gen7_forcewake_mt_LDADD = $(LDADD) -lpthread +@BUILD_TESTS_TRUE@gem_wait_render_timeout_LDADD = $(LDADD) -lrt +@BUILD_TESTS_TRUE@kms_flip_LDADD = $(LDADD) -lrt -lpthread +@BUILD_TESTS_TRUE@prime_nv_test_CFLAGS = $(AM_CFLAGS) $(DRM_NOUVEAU_CFLAGS) +@BUILD_TESTS_TRUE@prime_nv_test_LDADD = $(LDADD) $(DRM_NOUVEAU_LIBS) +@BUILD_TESTS_TRUE@prime_nv_api_CFLAGS = $(AM_CFLAGS) $(DRM_NOUVEAU_CFLAGS) +@BUILD_TESTS_TRUE@prime_nv_api_LDADD = $(LDADD) $(DRM_NOUVEAU_LIBS) +@BUILD_TESTS_TRUE@prime_nv_pcopy_CFLAGS = $(AM_CFLAGS) $(DRM_NOUVEAU_CFLAGS) +@BUILD_TESTS_TRUE@prime_nv_pcopy_LDADD = $(LDADD) $(DRM_NOUVEAU_LIBS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/Makefile.sources $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(srcdir)/Makefile.sources: + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +core_get_client_auth$(EXEEXT): $(core_get_client_auth_OBJECTS) $(core_get_client_auth_DEPENDENCIES) $(EXTRA_core_get_client_auth_DEPENDENCIES) + @rm -f core_get_client_auth$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(core_get_client_auth_OBJECTS) $(core_get_client_auth_LDADD) $(LIBS) + +core_getclient$(EXEEXT): $(core_getclient_OBJECTS) $(core_getclient_DEPENDENCIES) $(EXTRA_core_getclient_DEPENDENCIES) + @rm -f core_getclient$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(core_getclient_OBJECTS) $(core_getclient_LDADD) $(LIBS) + +core_getstats$(EXEEXT): $(core_getstats_OBJECTS) $(core_getstats_DEPENDENCIES) $(EXTRA_core_getstats_DEPENDENCIES) + @rm -f core_getstats$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(core_getstats_OBJECTS) $(core_getstats_LDADD) $(LIBS) + +core_getversion$(EXEEXT): $(core_getversion_OBJECTS) $(core_getversion_DEPENDENCIES) $(EXTRA_core_getversion_DEPENDENCIES) + @rm -f core_getversion$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(core_getversion_OBJECTS) $(core_getversion_LDADD) $(LIBS) + +ddi_compute_wrpll$(EXEEXT): $(ddi_compute_wrpll_OBJECTS) $(ddi_compute_wrpll_DEPENDENCIES) $(EXTRA_ddi_compute_wrpll_DEPENDENCIES) + @rm -f ddi_compute_wrpll$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(ddi_compute_wrpll_OBJECTS) $(ddi_compute_wrpll_LDADD) $(LIBS) + +drm_vma_limiter$(EXEEXT): $(drm_vma_limiter_OBJECTS) $(drm_vma_limiter_DEPENDENCIES) $(EXTRA_drm_vma_limiter_DEPENDENCIES) + @rm -f drm_vma_limiter$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(drm_vma_limiter_OBJECTS) $(drm_vma_limiter_LDADD) $(LIBS) + +drm_vma_limiter_cached$(EXEEXT): $(drm_vma_limiter_cached_OBJECTS) $(drm_vma_limiter_cached_DEPENDENCIES) $(EXTRA_drm_vma_limiter_cached_DEPENDENCIES) + @rm -f drm_vma_limiter_cached$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(drm_vma_limiter_cached_OBJECTS) $(drm_vma_limiter_cached_LDADD) $(LIBS) + +drm_vma_limiter_cpu$(EXEEXT): $(drm_vma_limiter_cpu_OBJECTS) $(drm_vma_limiter_cpu_DEPENDENCIES) $(EXTRA_drm_vma_limiter_cpu_DEPENDENCIES) + @rm -f drm_vma_limiter_cpu$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(drm_vma_limiter_cpu_OBJECTS) $(drm_vma_limiter_cpu_LDADD) $(LIBS) + +drm_vma_limiter_gtt$(EXEEXT): $(drm_vma_limiter_gtt_OBJECTS) $(drm_vma_limiter_gtt_DEPENDENCIES) $(EXTRA_drm_vma_limiter_gtt_DEPENDENCIES) + @rm -f drm_vma_limiter_gtt$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(drm_vma_limiter_gtt_OBJECTS) $(drm_vma_limiter_gtt_LDADD) $(LIBS) + +drv_hangman$(EXEEXT): $(drv_hangman_OBJECTS) $(drv_hangman_DEPENDENCIES) $(EXTRA_drv_hangman_DEPENDENCIES) + @rm -f drv_hangman$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(drv_hangman_OBJECTS) $(drv_hangman_LDADD) $(LIBS) + +drv_suspend$(EXEEXT): $(drv_suspend_OBJECTS) $(drv_suspend_DEPENDENCIES) $(EXTRA_drv_suspend_DEPENDENCIES) + @rm -f drv_suspend$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(drv_suspend_OBJECTS) $(drv_suspend_LDADD) $(LIBS) + +gem_alive$(EXEEXT): $(gem_alive_OBJECTS) $(gem_alive_DEPENDENCIES) $(EXTRA_gem_alive_DEPENDENCIES) + @rm -f gem_alive$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_alive_OBJECTS) $(gem_alive_LDADD) $(LIBS) + +gem_bad_address$(EXEEXT): $(gem_bad_address_OBJECTS) $(gem_bad_address_DEPENDENCIES) $(EXTRA_gem_bad_address_DEPENDENCIES) + @rm -f gem_bad_address$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_bad_address_OBJECTS) $(gem_bad_address_LDADD) $(LIBS) + +gem_bad_batch$(EXEEXT): $(gem_bad_batch_OBJECTS) $(gem_bad_batch_DEPENDENCIES) $(EXTRA_gem_bad_batch_DEPENDENCIES) + @rm -f gem_bad_batch$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_bad_batch_OBJECTS) $(gem_bad_batch_LDADD) $(LIBS) + +gem_bad_blit$(EXEEXT): $(gem_bad_blit_OBJECTS) $(gem_bad_blit_DEPENDENCIES) $(EXTRA_gem_bad_blit_DEPENDENCIES) + @rm -f gem_bad_blit$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_bad_blit_OBJECTS) $(gem_bad_blit_LDADD) $(LIBS) + +gem_bad_length$(EXEEXT): $(gem_bad_length_OBJECTS) $(gem_bad_length_DEPENDENCIES) $(EXTRA_gem_bad_length_DEPENDENCIES) + @rm -f gem_bad_length$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_bad_length_OBJECTS) $(gem_bad_length_LDADD) $(LIBS) + +gem_bad_reloc$(EXEEXT): $(gem_bad_reloc_OBJECTS) $(gem_bad_reloc_DEPENDENCIES) $(EXTRA_gem_bad_reloc_DEPENDENCIES) + @rm -f gem_bad_reloc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_bad_reloc_OBJECTS) $(gem_bad_reloc_LDADD) $(LIBS) + +gem_basic$(EXEEXT): $(gem_basic_OBJECTS) $(gem_basic_DEPENDENCIES) $(EXTRA_gem_basic_DEPENDENCIES) + @rm -f gem_basic$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_basic_OBJECTS) $(gem_basic_LDADD) $(LIBS) + +gem_caching$(EXEEXT): $(gem_caching_OBJECTS) $(gem_caching_DEPENDENCIES) $(EXTRA_gem_caching_DEPENDENCIES) + @rm -f gem_caching$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_caching_OBJECTS) $(gem_caching_LDADD) $(LIBS) + +gem_close_race$(EXEEXT): $(gem_close_race_OBJECTS) $(gem_close_race_DEPENDENCIES) $(EXTRA_gem_close_race_DEPENDENCIES) + @rm -f gem_close_race$(EXEEXT) + $(AM_V_CCLD)$(gem_close_race_LINK) $(gem_close_race_OBJECTS) $(gem_close_race_LDADD) $(LIBS) + +gem_concurrent_blit$(EXEEXT): $(gem_concurrent_blit_OBJECTS) $(gem_concurrent_blit_DEPENDENCIES) $(EXTRA_gem_concurrent_blit_DEPENDENCIES) + @rm -f gem_concurrent_blit$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_concurrent_blit_OBJECTS) $(gem_concurrent_blit_LDADD) $(LIBS) + +gem_cpu_reloc$(EXEEXT): $(gem_cpu_reloc_OBJECTS) $(gem_cpu_reloc_DEPENDENCIES) $(EXTRA_gem_cpu_reloc_DEPENDENCIES) + @rm -f gem_cpu_reloc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_cpu_reloc_OBJECTS) $(gem_cpu_reloc_LDADD) $(LIBS) + +gem_cs_prefetch$(EXEEXT): $(gem_cs_prefetch_OBJECTS) $(gem_cs_prefetch_DEPENDENCIES) $(EXTRA_gem_cs_prefetch_DEPENDENCIES) + @rm -f gem_cs_prefetch$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_cs_prefetch_OBJECTS) $(gem_cs_prefetch_LDADD) $(LIBS) + +gem_cs_tlb$(EXEEXT): $(gem_cs_tlb_OBJECTS) $(gem_cs_tlb_DEPENDENCIES) $(EXTRA_gem_cs_tlb_DEPENDENCIES) + @rm -f gem_cs_tlb$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_cs_tlb_OBJECTS) $(gem_cs_tlb_LDADD) $(LIBS) + +gem_ctx_bad_destroy$(EXEEXT): $(gem_ctx_bad_destroy_OBJECTS) $(gem_ctx_bad_destroy_DEPENDENCIES) $(EXTRA_gem_ctx_bad_destroy_DEPENDENCIES) + @rm -f gem_ctx_bad_destroy$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_ctx_bad_destroy_OBJECTS) $(gem_ctx_bad_destroy_LDADD) $(LIBS) + +gem_ctx_bad_exec$(EXEEXT): $(gem_ctx_bad_exec_OBJECTS) $(gem_ctx_bad_exec_DEPENDENCIES) $(EXTRA_gem_ctx_bad_exec_DEPENDENCIES) + @rm -f gem_ctx_bad_exec$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_ctx_bad_exec_OBJECTS) $(gem_ctx_bad_exec_LDADD) $(LIBS) + +gem_ctx_basic$(EXEEXT): $(gem_ctx_basic_OBJECTS) $(gem_ctx_basic_DEPENDENCIES) $(EXTRA_gem_ctx_basic_DEPENDENCIES) + @rm -f gem_ctx_basic$(EXEEXT) + $(AM_V_CCLD)$(gem_ctx_basic_LINK) $(gem_ctx_basic_OBJECTS) $(gem_ctx_basic_LDADD) $(LIBS) + +gem_ctx_create$(EXEEXT): $(gem_ctx_create_OBJECTS) $(gem_ctx_create_DEPENDENCIES) $(EXTRA_gem_ctx_create_DEPENDENCIES) + @rm -f gem_ctx_create$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_ctx_create_OBJECTS) $(gem_ctx_create_LDADD) $(LIBS) + +gem_ctx_exec$(EXEEXT): $(gem_ctx_exec_OBJECTS) $(gem_ctx_exec_DEPENDENCIES) $(EXTRA_gem_ctx_exec_DEPENDENCIES) + @rm -f gem_ctx_exec$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_ctx_exec_OBJECTS) $(gem_ctx_exec_LDADD) $(LIBS) + +gem_double_irq_loop$(EXEEXT): $(gem_double_irq_loop_OBJECTS) $(gem_double_irq_loop_DEPENDENCIES) $(EXTRA_gem_double_irq_loop_DEPENDENCIES) + @rm -f gem_double_irq_loop$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_double_irq_loop_OBJECTS) $(gem_double_irq_loop_LDADD) $(LIBS) + +gem_dummy_reloc_loop$(EXEEXT): $(gem_dummy_reloc_loop_OBJECTS) $(gem_dummy_reloc_loop_DEPENDENCIES) $(EXTRA_gem_dummy_reloc_loop_DEPENDENCIES) + @rm -f gem_dummy_reloc_loop$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_dummy_reloc_loop_OBJECTS) $(gem_dummy_reloc_loop_LDADD) $(LIBS) + +gem_evict_alignment$(EXEEXT): $(gem_evict_alignment_OBJECTS) $(gem_evict_alignment_DEPENDENCIES) $(EXTRA_gem_evict_alignment_DEPENDENCIES) + @rm -f gem_evict_alignment$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_evict_alignment_OBJECTS) $(gem_evict_alignment_LDADD) $(LIBS) + +gem_evict_everything$(EXEEXT): $(gem_evict_everything_OBJECTS) $(gem_evict_everything_DEPENDENCIES) $(EXTRA_gem_evict_everything_DEPENDENCIES) + @rm -f gem_evict_everything$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_evict_everything_OBJECTS) $(gem_evict_everything_LDADD) $(LIBS) + +gem_exec_bad_domains$(EXEEXT): $(gem_exec_bad_domains_OBJECTS) $(gem_exec_bad_domains_DEPENDENCIES) $(EXTRA_gem_exec_bad_domains_DEPENDENCIES) + @rm -f gem_exec_bad_domains$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_exec_bad_domains_OBJECTS) $(gem_exec_bad_domains_LDADD) $(LIBS) + +gem_exec_big$(EXEEXT): $(gem_exec_big_OBJECTS) $(gem_exec_big_DEPENDENCIES) $(EXTRA_gem_exec_big_DEPENDENCIES) + @rm -f gem_exec_big$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_exec_big_OBJECTS) $(gem_exec_big_LDADD) $(LIBS) + +gem_exec_blt$(EXEEXT): $(gem_exec_blt_OBJECTS) $(gem_exec_blt_DEPENDENCIES) $(EXTRA_gem_exec_blt_DEPENDENCIES) + @rm -f gem_exec_blt$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_exec_blt_OBJECTS) $(gem_exec_blt_LDADD) $(LIBS) + +gem_exec_faulting_reloc$(EXEEXT): $(gem_exec_faulting_reloc_OBJECTS) $(gem_exec_faulting_reloc_DEPENDENCIES) $(EXTRA_gem_exec_faulting_reloc_DEPENDENCIES) + @rm -f gem_exec_faulting_reloc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_exec_faulting_reloc_OBJECTS) $(gem_exec_faulting_reloc_LDADD) $(LIBS) + +gem_exec_lut_handle$(EXEEXT): $(gem_exec_lut_handle_OBJECTS) $(gem_exec_lut_handle_DEPENDENCIES) $(EXTRA_gem_exec_lut_handle_DEPENDENCIES) + @rm -f gem_exec_lut_handle$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_exec_lut_handle_OBJECTS) $(gem_exec_lut_handle_LDADD) $(LIBS) + +gem_exec_nop$(EXEEXT): $(gem_exec_nop_OBJECTS) $(gem_exec_nop_DEPENDENCIES) $(EXTRA_gem_exec_nop_DEPENDENCIES) + @rm -f gem_exec_nop$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_exec_nop_OBJECTS) $(gem_exec_nop_LDADD) $(LIBS) + +gem_exec_params$(EXEEXT): $(gem_exec_params_OBJECTS) $(gem_exec_params_DEPENDENCIES) $(EXTRA_gem_exec_params_DEPENDENCIES) + @rm -f gem_exec_params$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_exec_params_OBJECTS) $(gem_exec_params_LDADD) $(LIBS) + +gem_exec_parse$(EXEEXT): $(gem_exec_parse_OBJECTS) $(gem_exec_parse_DEPENDENCIES) $(EXTRA_gem_exec_parse_DEPENDENCIES) + @rm -f gem_exec_parse$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_exec_parse_OBJECTS) $(gem_exec_parse_LDADD) $(LIBS) + +gem_fd_exhaustion$(EXEEXT): $(gem_fd_exhaustion_OBJECTS) $(gem_fd_exhaustion_DEPENDENCIES) $(EXTRA_gem_fd_exhaustion_DEPENDENCIES) + @rm -f gem_fd_exhaustion$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_fd_exhaustion_OBJECTS) $(gem_fd_exhaustion_LDADD) $(LIBS) + +gem_fence_thrash$(EXEEXT): $(gem_fence_thrash_OBJECTS) $(gem_fence_thrash_DEPENDENCIES) $(EXTRA_gem_fence_thrash_DEPENDENCIES) + @rm -f gem_fence_thrash$(EXEEXT) + $(AM_V_CCLD)$(gem_fence_thrash_LINK) $(gem_fence_thrash_OBJECTS) $(gem_fence_thrash_LDADD) $(LIBS) + +gem_fenced_exec_thrash$(EXEEXT): $(gem_fenced_exec_thrash_OBJECTS) $(gem_fenced_exec_thrash_DEPENDENCIES) $(EXTRA_gem_fenced_exec_thrash_DEPENDENCIES) + @rm -f gem_fenced_exec_thrash$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_fenced_exec_thrash_OBJECTS) $(gem_fenced_exec_thrash_LDADD) $(LIBS) + +gem_flink$(EXEEXT): $(gem_flink_OBJECTS) $(gem_flink_DEPENDENCIES) $(EXTRA_gem_flink_DEPENDENCIES) + @rm -f gem_flink$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_flink_OBJECTS) $(gem_flink_LDADD) $(LIBS) + +gem_flink_race$(EXEEXT): $(gem_flink_race_OBJECTS) $(gem_flink_race_DEPENDENCIES) $(EXTRA_gem_flink_race_DEPENDENCIES) + @rm -f gem_flink_race$(EXEEXT) + $(AM_V_CCLD)$(gem_flink_race_LINK) $(gem_flink_race_OBJECTS) $(gem_flink_race_LDADD) $(LIBS) + +gem_gtt_cpu_tlb$(EXEEXT): $(gem_gtt_cpu_tlb_OBJECTS) $(gem_gtt_cpu_tlb_DEPENDENCIES) $(EXTRA_gem_gtt_cpu_tlb_DEPENDENCIES) + @rm -f gem_gtt_cpu_tlb$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_gtt_cpu_tlb_OBJECTS) $(gem_gtt_cpu_tlb_LDADD) $(LIBS) + +gem_gtt_hog$(EXEEXT): $(gem_gtt_hog_OBJECTS) $(gem_gtt_hog_DEPENDENCIES) $(EXTRA_gem_gtt_hog_DEPENDENCIES) + @rm -f gem_gtt_hog$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_gtt_hog_OBJECTS) $(gem_gtt_hog_LDADD) $(LIBS) + +gem_gtt_speed$(EXEEXT): $(gem_gtt_speed_OBJECTS) $(gem_gtt_speed_DEPENDENCIES) $(EXTRA_gem_gtt_speed_DEPENDENCIES) + @rm -f gem_gtt_speed$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_gtt_speed_OBJECTS) $(gem_gtt_speed_LDADD) $(LIBS) + +gem_hang$(EXEEXT): $(gem_hang_OBJECTS) $(gem_hang_DEPENDENCIES) $(EXTRA_gem_hang_DEPENDENCIES) + @rm -f gem_hang$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_hang_OBJECTS) $(gem_hang_LDADD) $(LIBS) + +gem_hangcheck_forcewake$(EXEEXT): $(gem_hangcheck_forcewake_OBJECTS) $(gem_hangcheck_forcewake_DEPENDENCIES) $(EXTRA_gem_hangcheck_forcewake_DEPENDENCIES) + @rm -f gem_hangcheck_forcewake$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_hangcheck_forcewake_OBJECTS) $(gem_hangcheck_forcewake_LDADD) $(LIBS) + +gem_largeobject$(EXEEXT): $(gem_largeobject_OBJECTS) $(gem_largeobject_DEPENDENCIES) $(EXTRA_gem_largeobject_DEPENDENCIES) + @rm -f gem_largeobject$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_largeobject_OBJECTS) $(gem_largeobject_LDADD) $(LIBS) + +gem_linear_blits$(EXEEXT): $(gem_linear_blits_OBJECTS) $(gem_linear_blits_DEPENDENCIES) $(EXTRA_gem_linear_blits_DEPENDENCIES) + @rm -f gem_linear_blits$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_linear_blits_OBJECTS) $(gem_linear_blits_LDADD) $(LIBS) + +gem_lut_handle$(EXEEXT): $(gem_lut_handle_OBJECTS) $(gem_lut_handle_DEPENDENCIES) $(EXTRA_gem_lut_handle_DEPENDENCIES) + @rm -f gem_lut_handle$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_lut_handle_OBJECTS) $(gem_lut_handle_LDADD) $(LIBS) + +gem_madvise$(EXEEXT): $(gem_madvise_OBJECTS) $(gem_madvise_DEPENDENCIES) $(EXTRA_gem_madvise_DEPENDENCIES) + @rm -f gem_madvise$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_madvise_OBJECTS) $(gem_madvise_LDADD) $(LIBS) + +gem_media_fill$(EXEEXT): $(gem_media_fill_OBJECTS) $(gem_media_fill_DEPENDENCIES) $(EXTRA_gem_media_fill_DEPENDENCIES) + @rm -f gem_media_fill$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_media_fill_OBJECTS) $(gem_media_fill_LDADD) $(LIBS) + +gem_mmap$(EXEEXT): $(gem_mmap_OBJECTS) $(gem_mmap_DEPENDENCIES) $(EXTRA_gem_mmap_DEPENDENCIES) + @rm -f gem_mmap$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_mmap_OBJECTS) $(gem_mmap_LDADD) $(LIBS) + +gem_mmap_gtt$(EXEEXT): $(gem_mmap_gtt_OBJECTS) $(gem_mmap_gtt_DEPENDENCIES) $(EXTRA_gem_mmap_gtt_DEPENDENCIES) + @rm -f gem_mmap_gtt$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_mmap_gtt_OBJECTS) $(gem_mmap_gtt_LDADD) $(LIBS) + +gem_mmap_offset_exhaustion$(EXEEXT): $(gem_mmap_offset_exhaustion_OBJECTS) $(gem_mmap_offset_exhaustion_DEPENDENCIES) $(EXTRA_gem_mmap_offset_exhaustion_DEPENDENCIES) + @rm -f gem_mmap_offset_exhaustion$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_mmap_offset_exhaustion_OBJECTS) $(gem_mmap_offset_exhaustion_LDADD) $(LIBS) + +gem_multi_bsd_sync_loop$(EXEEXT): $(gem_multi_bsd_sync_loop_OBJECTS) $(gem_multi_bsd_sync_loop_DEPENDENCIES) $(EXTRA_gem_multi_bsd_sync_loop_DEPENDENCIES) + @rm -f gem_multi_bsd_sync_loop$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_multi_bsd_sync_loop_OBJECTS) $(gem_multi_bsd_sync_loop_LDADD) $(LIBS) + +gem_non_secure_batch$(EXEEXT): $(gem_non_secure_batch_OBJECTS) $(gem_non_secure_batch_DEPENDENCIES) $(EXTRA_gem_non_secure_batch_DEPENDENCIES) + @rm -f gem_non_secure_batch$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_non_secure_batch_OBJECTS) $(gem_non_secure_batch_LDADD) $(LIBS) + +gem_partial_pwrite_pread$(EXEEXT): $(gem_partial_pwrite_pread_OBJECTS) $(gem_partial_pwrite_pread_DEPENDENCIES) $(EXTRA_gem_partial_pwrite_pread_DEPENDENCIES) + @rm -f gem_partial_pwrite_pread$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_partial_pwrite_pread_OBJECTS) $(gem_partial_pwrite_pread_LDADD) $(LIBS) + +gem_persistent_relocs$(EXEEXT): $(gem_persistent_relocs_OBJECTS) $(gem_persistent_relocs_DEPENDENCIES) $(EXTRA_gem_persistent_relocs_DEPENDENCIES) + @rm -f gem_persistent_relocs$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_persistent_relocs_OBJECTS) $(gem_persistent_relocs_LDADD) $(LIBS) + +gem_pin$(EXEEXT): $(gem_pin_OBJECTS) $(gem_pin_DEPENDENCIES) $(EXTRA_gem_pin_DEPENDENCIES) + @rm -f gem_pin$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_pin_OBJECTS) $(gem_pin_LDADD) $(LIBS) + +gem_pipe_control_store_loop$(EXEEXT): $(gem_pipe_control_store_loop_OBJECTS) $(gem_pipe_control_store_loop_DEPENDENCIES) $(EXTRA_gem_pipe_control_store_loop_DEPENDENCIES) + @rm -f gem_pipe_control_store_loop$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_pipe_control_store_loop_OBJECTS) $(gem_pipe_control_store_loop_LDADD) $(LIBS) + +gem_pread$(EXEEXT): $(gem_pread_OBJECTS) $(gem_pread_DEPENDENCIES) $(EXTRA_gem_pread_DEPENDENCIES) + @rm -f gem_pread$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_pread_OBJECTS) $(gem_pread_LDADD) $(LIBS) + +gem_pread_after_blit$(EXEEXT): $(gem_pread_after_blit_OBJECTS) $(gem_pread_after_blit_DEPENDENCIES) $(EXTRA_gem_pread_after_blit_DEPENDENCIES) + @rm -f gem_pread_after_blit$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_pread_after_blit_OBJECTS) $(gem_pread_after_blit_LDADD) $(LIBS) + +gem_pwrite$(EXEEXT): $(gem_pwrite_OBJECTS) $(gem_pwrite_DEPENDENCIES) $(EXTRA_gem_pwrite_DEPENDENCIES) + @rm -f gem_pwrite$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_pwrite_OBJECTS) $(gem_pwrite_LDADD) $(LIBS) + +gem_pwrite_pread$(EXEEXT): $(gem_pwrite_pread_OBJECTS) $(gem_pwrite_pread_DEPENDENCIES) $(EXTRA_gem_pwrite_pread_DEPENDENCIES) + @rm -f gem_pwrite_pread$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_pwrite_pread_OBJECTS) $(gem_pwrite_pread_LDADD) $(LIBS) + +gem_readwrite$(EXEEXT): $(gem_readwrite_OBJECTS) $(gem_readwrite_DEPENDENCIES) $(EXTRA_gem_readwrite_DEPENDENCIES) + @rm -f gem_readwrite$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_readwrite_OBJECTS) $(gem_readwrite_LDADD) $(LIBS) + +gem_reg_read$(EXEEXT): $(gem_reg_read_OBJECTS) $(gem_reg_read_DEPENDENCIES) $(EXTRA_gem_reg_read_DEPENDENCIES) + @rm -f gem_reg_read$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_reg_read_OBJECTS) $(gem_reg_read_LDADD) $(LIBS) + +gem_reloc_overflow$(EXEEXT): $(gem_reloc_overflow_OBJECTS) $(gem_reloc_overflow_DEPENDENCIES) $(EXTRA_gem_reloc_overflow_DEPENDENCIES) + @rm -f gem_reloc_overflow$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_reloc_overflow_OBJECTS) $(gem_reloc_overflow_LDADD) $(LIBS) + +gem_reloc_vs_gpu$(EXEEXT): $(gem_reloc_vs_gpu_OBJECTS) $(gem_reloc_vs_gpu_DEPENDENCIES) $(EXTRA_gem_reloc_vs_gpu_DEPENDENCIES) + @rm -f gem_reloc_vs_gpu$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_reloc_vs_gpu_OBJECTS) $(gem_reloc_vs_gpu_LDADD) $(LIBS) + +gem_render_copy$(EXEEXT): $(gem_render_copy_OBJECTS) $(gem_render_copy_DEPENDENCIES) $(EXTRA_gem_render_copy_DEPENDENCIES) + @rm -f gem_render_copy$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_render_copy_OBJECTS) $(gem_render_copy_LDADD) $(LIBS) + +gem_render_copy_redux$(EXEEXT): $(gem_render_copy_redux_OBJECTS) $(gem_render_copy_redux_DEPENDENCIES) $(EXTRA_gem_render_copy_redux_DEPENDENCIES) + @rm -f gem_render_copy_redux$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_render_copy_redux_OBJECTS) $(gem_render_copy_redux_LDADD) $(LIBS) + +gem_render_linear_blits$(EXEEXT): $(gem_render_linear_blits_OBJECTS) $(gem_render_linear_blits_DEPENDENCIES) $(EXTRA_gem_render_linear_blits_DEPENDENCIES) + @rm -f gem_render_linear_blits$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_render_linear_blits_OBJECTS) $(gem_render_linear_blits_LDADD) $(LIBS) + +gem_render_tiled_blits$(EXEEXT): $(gem_render_tiled_blits_OBJECTS) $(gem_render_tiled_blits_DEPENDENCIES) $(EXTRA_gem_render_tiled_blits_DEPENDENCIES) + @rm -f gem_render_tiled_blits$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_render_tiled_blits_OBJECTS) $(gem_render_tiled_blits_LDADD) $(LIBS) + +gem_reset_stats$(EXEEXT): $(gem_reset_stats_OBJECTS) $(gem_reset_stats_DEPENDENCIES) $(EXTRA_gem_reset_stats_DEPENDENCIES) + @rm -f gem_reset_stats$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_reset_stats_OBJECTS) $(gem_reset_stats_LDADD) $(LIBS) + +gem_ring_sync_copy$(EXEEXT): $(gem_ring_sync_copy_OBJECTS) $(gem_ring_sync_copy_DEPENDENCIES) $(EXTRA_gem_ring_sync_copy_DEPENDENCIES) + @rm -f gem_ring_sync_copy$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_ring_sync_copy_OBJECTS) $(gem_ring_sync_copy_LDADD) $(LIBS) + +gem_ring_sync_loop$(EXEEXT): $(gem_ring_sync_loop_OBJECTS) $(gem_ring_sync_loop_DEPENDENCIES) $(EXTRA_gem_ring_sync_loop_DEPENDENCIES) + @rm -f gem_ring_sync_loop$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_ring_sync_loop_OBJECTS) $(gem_ring_sync_loop_LDADD) $(LIBS) + +gem_ringfill$(EXEEXT): $(gem_ringfill_OBJECTS) $(gem_ringfill_DEPENDENCIES) $(EXTRA_gem_ringfill_DEPENDENCIES) + @rm -f gem_ringfill$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_ringfill_OBJECTS) $(gem_ringfill_LDADD) $(LIBS) + +gem_seqno_wrap$(EXEEXT): $(gem_seqno_wrap_OBJECTS) $(gem_seqno_wrap_DEPENDENCIES) $(EXTRA_gem_seqno_wrap_DEPENDENCIES) + @rm -f gem_seqno_wrap$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_seqno_wrap_OBJECTS) $(gem_seqno_wrap_LDADD) $(LIBS) + +gem_set_tiling_vs_blt$(EXEEXT): $(gem_set_tiling_vs_blt_OBJECTS) $(gem_set_tiling_vs_blt_DEPENDENCIES) $(EXTRA_gem_set_tiling_vs_blt_DEPENDENCIES) + @rm -f gem_set_tiling_vs_blt$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_set_tiling_vs_blt_OBJECTS) $(gem_set_tiling_vs_blt_LDADD) $(LIBS) + +gem_set_tiling_vs_gtt$(EXEEXT): $(gem_set_tiling_vs_gtt_OBJECTS) $(gem_set_tiling_vs_gtt_DEPENDENCIES) $(EXTRA_gem_set_tiling_vs_gtt_DEPENDENCIES) + @rm -f gem_set_tiling_vs_gtt$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_set_tiling_vs_gtt_OBJECTS) $(gem_set_tiling_vs_gtt_LDADD) $(LIBS) + +gem_set_tiling_vs_pwrite$(EXEEXT): $(gem_set_tiling_vs_pwrite_OBJECTS) $(gem_set_tiling_vs_pwrite_DEPENDENCIES) $(EXTRA_gem_set_tiling_vs_pwrite_DEPENDENCIES) + @rm -f gem_set_tiling_vs_pwrite$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_set_tiling_vs_pwrite_OBJECTS) $(gem_set_tiling_vs_pwrite_LDADD) $(LIBS) + +gem_storedw_batches_loop$(EXEEXT): $(gem_storedw_batches_loop_OBJECTS) $(gem_storedw_batches_loop_DEPENDENCIES) $(EXTRA_gem_storedw_batches_loop_DEPENDENCIES) + @rm -f gem_storedw_batches_loop$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_storedw_batches_loop_OBJECTS) $(gem_storedw_batches_loop_LDADD) $(LIBS) + +gem_storedw_loop_blt$(EXEEXT): $(gem_storedw_loop_blt_OBJECTS) $(gem_storedw_loop_blt_DEPENDENCIES) $(EXTRA_gem_storedw_loop_blt_DEPENDENCIES) + @rm -f gem_storedw_loop_blt$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_storedw_loop_blt_OBJECTS) $(gem_storedw_loop_blt_LDADD) $(LIBS) + +gem_storedw_loop_bsd$(EXEEXT): $(gem_storedw_loop_bsd_OBJECTS) $(gem_storedw_loop_bsd_DEPENDENCIES) $(EXTRA_gem_storedw_loop_bsd_DEPENDENCIES) + @rm -f gem_storedw_loop_bsd$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_storedw_loop_bsd_OBJECTS) $(gem_storedw_loop_bsd_LDADD) $(LIBS) + +gem_storedw_loop_render$(EXEEXT): $(gem_storedw_loop_render_OBJECTS) $(gem_storedw_loop_render_DEPENDENCIES) $(EXTRA_gem_storedw_loop_render_DEPENDENCIES) + @rm -f gem_storedw_loop_render$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_storedw_loop_render_OBJECTS) $(gem_storedw_loop_render_LDADD) $(LIBS) + +gem_storedw_loop_vebox$(EXEEXT): $(gem_storedw_loop_vebox_OBJECTS) $(gem_storedw_loop_vebox_DEPENDENCIES) $(EXTRA_gem_storedw_loop_vebox_DEPENDENCIES) + @rm -f gem_storedw_loop_vebox$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_storedw_loop_vebox_OBJECTS) $(gem_storedw_loop_vebox_LDADD) $(LIBS) + +gem_stress$(EXEEXT): $(gem_stress_OBJECTS) $(gem_stress_DEPENDENCIES) $(EXTRA_gem_stress_DEPENDENCIES) + @rm -f gem_stress$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_stress_OBJECTS) $(gem_stress_LDADD) $(LIBS) + +gem_threaded_access_tiled$(EXEEXT): $(gem_threaded_access_tiled_OBJECTS) $(gem_threaded_access_tiled_DEPENDENCIES) $(EXTRA_gem_threaded_access_tiled_DEPENDENCIES) + @rm -f gem_threaded_access_tiled$(EXEEXT) + $(AM_V_CCLD)$(gem_threaded_access_tiled_LINK) $(gem_threaded_access_tiled_OBJECTS) $(gem_threaded_access_tiled_LDADD) $(LIBS) + +gem_tiled_blits$(EXEEXT): $(gem_tiled_blits_OBJECTS) $(gem_tiled_blits_DEPENDENCIES) $(EXTRA_gem_tiled_blits_DEPENDENCIES) + @rm -f gem_tiled_blits$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_tiled_blits_OBJECTS) $(gem_tiled_blits_LDADD) $(LIBS) + +gem_tiled_fence_blits$(EXEEXT): $(gem_tiled_fence_blits_OBJECTS) $(gem_tiled_fence_blits_DEPENDENCIES) $(EXTRA_gem_tiled_fence_blits_DEPENDENCIES) + @rm -f gem_tiled_fence_blits$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_tiled_fence_blits_OBJECTS) $(gem_tiled_fence_blits_LDADD) $(LIBS) + +gem_tiled_partial_pwrite_pread$(EXEEXT): $(gem_tiled_partial_pwrite_pread_OBJECTS) $(gem_tiled_partial_pwrite_pread_DEPENDENCIES) $(EXTRA_gem_tiled_partial_pwrite_pread_DEPENDENCIES) + @rm -f gem_tiled_partial_pwrite_pread$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_tiled_partial_pwrite_pread_OBJECTS) $(gem_tiled_partial_pwrite_pread_LDADD) $(LIBS) + +gem_tiled_pread$(EXEEXT): $(gem_tiled_pread_OBJECTS) $(gem_tiled_pread_DEPENDENCIES) $(EXTRA_gem_tiled_pread_DEPENDENCIES) + @rm -f gem_tiled_pread$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_tiled_pread_OBJECTS) $(gem_tiled_pread_LDADD) $(LIBS) + +gem_tiled_pread_pwrite$(EXEEXT): $(gem_tiled_pread_pwrite_OBJECTS) $(gem_tiled_pread_pwrite_DEPENDENCIES) $(EXTRA_gem_tiled_pread_pwrite_DEPENDENCIES) + @rm -f gem_tiled_pread_pwrite$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_tiled_pread_pwrite_OBJECTS) $(gem_tiled_pread_pwrite_LDADD) $(LIBS) + +gem_tiled_swapping$(EXEEXT): $(gem_tiled_swapping_OBJECTS) $(gem_tiled_swapping_DEPENDENCIES) $(EXTRA_gem_tiled_swapping_DEPENDENCIES) + @rm -f gem_tiled_swapping$(EXEEXT) + $(AM_V_CCLD)$(gem_tiled_swapping_LINK) $(gem_tiled_swapping_OBJECTS) $(gem_tiled_swapping_LDADD) $(LIBS) + +gem_tiling_max_stride$(EXEEXT): $(gem_tiling_max_stride_OBJECTS) $(gem_tiling_max_stride_DEPENDENCIES) $(EXTRA_gem_tiling_max_stride_DEPENDENCIES) + @rm -f gem_tiling_max_stride$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_tiling_max_stride_OBJECTS) $(gem_tiling_max_stride_LDADD) $(LIBS) + +gem_unfence_active_buffers$(EXEEXT): $(gem_unfence_active_buffers_OBJECTS) $(gem_unfence_active_buffers_DEPENDENCIES) $(EXTRA_gem_unfence_active_buffers_DEPENDENCIES) + @rm -f gem_unfence_active_buffers$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_unfence_active_buffers_OBJECTS) $(gem_unfence_active_buffers_LDADD) $(LIBS) + +gem_unref_active_buffers$(EXEEXT): $(gem_unref_active_buffers_OBJECTS) $(gem_unref_active_buffers_DEPENDENCIES) $(EXTRA_gem_unref_active_buffers_DEPENDENCIES) + @rm -f gem_unref_active_buffers$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_unref_active_buffers_OBJECTS) $(gem_unref_active_buffers_LDADD) $(LIBS) + +gem_userptr_blits$(EXEEXT): $(gem_userptr_blits_OBJECTS) $(gem_userptr_blits_DEPENDENCIES) $(EXTRA_gem_userptr_blits_DEPENDENCIES) + @rm -f gem_userptr_blits$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_userptr_blits_OBJECTS) $(gem_userptr_blits_LDADD) $(LIBS) + +gem_wait_render_timeout$(EXEEXT): $(gem_wait_render_timeout_OBJECTS) $(gem_wait_render_timeout_DEPENDENCIES) $(EXTRA_gem_wait_render_timeout_DEPENDENCIES) + @rm -f gem_wait_render_timeout$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_wait_render_timeout_OBJECTS) $(gem_wait_render_timeout_LDADD) $(LIBS) + +gem_write_read_ring_switch$(EXEEXT): $(gem_write_read_ring_switch_OBJECTS) $(gem_write_read_ring_switch_DEPENDENCIES) $(EXTRA_gem_write_read_ring_switch_DEPENDENCIES) + @rm -f gem_write_read_ring_switch$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gem_write_read_ring_switch_OBJECTS) $(gem_write_read_ring_switch_LDADD) $(LIBS) + +gen3_mixed_blits$(EXEEXT): $(gen3_mixed_blits_OBJECTS) $(gen3_mixed_blits_DEPENDENCIES) $(EXTRA_gen3_mixed_blits_DEPENDENCIES) + @rm -f gen3_mixed_blits$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gen3_mixed_blits_OBJECTS) $(gen3_mixed_blits_LDADD) $(LIBS) + +gen3_render_linear_blits$(EXEEXT): $(gen3_render_linear_blits_OBJECTS) $(gen3_render_linear_blits_DEPENDENCIES) $(EXTRA_gen3_render_linear_blits_DEPENDENCIES) + @rm -f gen3_render_linear_blits$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gen3_render_linear_blits_OBJECTS) $(gen3_render_linear_blits_LDADD) $(LIBS) + +gen3_render_mixed_blits$(EXEEXT): $(gen3_render_mixed_blits_OBJECTS) $(gen3_render_mixed_blits_DEPENDENCIES) $(EXTRA_gen3_render_mixed_blits_DEPENDENCIES) + @rm -f gen3_render_mixed_blits$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gen3_render_mixed_blits_OBJECTS) $(gen3_render_mixed_blits_LDADD) $(LIBS) + +gen3_render_tiledx_blits$(EXEEXT): $(gen3_render_tiledx_blits_OBJECTS) $(gen3_render_tiledx_blits_DEPENDENCIES) $(EXTRA_gen3_render_tiledx_blits_DEPENDENCIES) + @rm -f gen3_render_tiledx_blits$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gen3_render_tiledx_blits_OBJECTS) $(gen3_render_tiledx_blits_LDADD) $(LIBS) + +gen3_render_tiledy_blits$(EXEEXT): $(gen3_render_tiledy_blits_OBJECTS) $(gen3_render_tiledy_blits_DEPENDENCIES) $(EXTRA_gen3_render_tiledy_blits_DEPENDENCIES) + @rm -f gen3_render_tiledy_blits$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gen3_render_tiledy_blits_OBJECTS) $(gen3_render_tiledy_blits_LDADD) $(LIBS) + +gen7_forcewake_mt$(EXEEXT): $(gen7_forcewake_mt_OBJECTS) $(gen7_forcewake_mt_DEPENDENCIES) $(EXTRA_gen7_forcewake_mt_DEPENDENCIES) + @rm -f gen7_forcewake_mt$(EXEEXT) + $(AM_V_CCLD)$(gen7_forcewake_mt_LINK) $(gen7_forcewake_mt_OBJECTS) $(gen7_forcewake_mt_LDADD) $(LIBS) + +igt_fork_helper$(EXEEXT): $(igt_fork_helper_OBJECTS) $(igt_fork_helper_DEPENDENCIES) $(EXTRA_igt_fork_helper_DEPENDENCIES) + @rm -f igt_fork_helper$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(igt_fork_helper_OBJECTS) $(igt_fork_helper_LDADD) $(LIBS) + +igt_list_only$(EXEEXT): $(igt_list_only_OBJECTS) $(igt_list_only_DEPENDENCIES) $(EXTRA_igt_list_only_DEPENDENCIES) + @rm -f igt_list_only$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(igt_list_only_OBJECTS) $(igt_list_only_LDADD) $(LIBS) + +igt_no_exit$(EXEEXT): $(igt_no_exit_OBJECTS) $(igt_no_exit_DEPENDENCIES) $(EXTRA_igt_no_exit_DEPENDENCIES) + @rm -f igt_no_exit$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(igt_no_exit_OBJECTS) $(igt_no_exit_LDADD) $(LIBS) + +igt_no_exit_list_only$(EXEEXT): $(igt_no_exit_list_only_OBJECTS) $(igt_no_exit_list_only_DEPENDENCIES) $(EXTRA_igt_no_exit_list_only_DEPENDENCIES) + @rm -f igt_no_exit_list_only$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(igt_no_exit_list_only_OBJECTS) $(igt_no_exit_list_only_LDADD) $(LIBS) + +igt_no_subtest$(EXEEXT): $(igt_no_subtest_OBJECTS) $(igt_no_subtest_DEPENDENCIES) $(EXTRA_igt_no_subtest_DEPENDENCIES) + @rm -f igt_no_subtest$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(igt_no_subtest_OBJECTS) $(igt_no_subtest_LDADD) $(LIBS) + +igt_simulation$(EXEEXT): $(igt_simulation_OBJECTS) $(igt_simulation_DEPENDENCIES) $(EXTRA_igt_simulation_DEPENDENCIES) + @rm -f igt_simulation$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(igt_simulation_OBJECTS) $(igt_simulation_LDADD) $(LIBS) + +kms_addfb$(EXEEXT): $(kms_addfb_OBJECTS) $(kms_addfb_DEPENDENCIES) $(EXTRA_kms_addfb_DEPENDENCIES) + @rm -f kms_addfb$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(kms_addfb_OBJECTS) $(kms_addfb_LDADD) $(LIBS) + +kms_cursor_crc$(EXEEXT): $(kms_cursor_crc_OBJECTS) $(kms_cursor_crc_DEPENDENCIES) $(EXTRA_kms_cursor_crc_DEPENDENCIES) + @rm -f kms_cursor_crc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(kms_cursor_crc_OBJECTS) $(kms_cursor_crc_LDADD) $(LIBS) + +kms_fbc_crc$(EXEEXT): $(kms_fbc_crc_OBJECTS) $(kms_fbc_crc_DEPENDENCIES) $(EXTRA_kms_fbc_crc_DEPENDENCIES) + @rm -f kms_fbc_crc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(kms_fbc_crc_OBJECTS) $(kms_fbc_crc_LDADD) $(LIBS) + +kms_fence_pin_leak$(EXEEXT): $(kms_fence_pin_leak_OBJECTS) $(kms_fence_pin_leak_DEPENDENCIES) $(EXTRA_kms_fence_pin_leak_DEPENDENCIES) + @rm -f kms_fence_pin_leak$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(kms_fence_pin_leak_OBJECTS) $(kms_fence_pin_leak_LDADD) $(LIBS) + +kms_flip$(EXEEXT): $(kms_flip_OBJECTS) $(kms_flip_DEPENDENCIES) $(EXTRA_kms_flip_DEPENDENCIES) + @rm -f kms_flip$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(kms_flip_OBJECTS) $(kms_flip_LDADD) $(LIBS) + +kms_flip_tiling$(EXEEXT): $(kms_flip_tiling_OBJECTS) $(kms_flip_tiling_DEPENDENCIES) $(EXTRA_kms_flip_tiling_DEPENDENCIES) + @rm -f kms_flip_tiling$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(kms_flip_tiling_OBJECTS) $(kms_flip_tiling_LDADD) $(LIBS) + +kms_mmio_vs_cs_flip$(EXEEXT): $(kms_mmio_vs_cs_flip_OBJECTS) $(kms_mmio_vs_cs_flip_DEPENDENCIES) $(EXTRA_kms_mmio_vs_cs_flip_DEPENDENCIES) + @rm -f kms_mmio_vs_cs_flip$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(kms_mmio_vs_cs_flip_OBJECTS) $(kms_mmio_vs_cs_flip_LDADD) $(LIBS) + +kms_pipe_crc_basic$(EXEEXT): $(kms_pipe_crc_basic_OBJECTS) $(kms_pipe_crc_basic_DEPENDENCIES) $(EXTRA_kms_pipe_crc_basic_DEPENDENCIES) + @rm -f kms_pipe_crc_basic$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(kms_pipe_crc_basic_OBJECTS) $(kms_pipe_crc_basic_LDADD) $(LIBS) + +kms_plane$(EXEEXT): $(kms_plane_OBJECTS) $(kms_plane_DEPENDENCIES) $(EXTRA_kms_plane_DEPENDENCIES) + @rm -f kms_plane$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(kms_plane_OBJECTS) $(kms_plane_LDADD) $(LIBS) + +kms_render$(EXEEXT): $(kms_render_OBJECTS) $(kms_render_DEPENDENCIES) $(EXTRA_kms_render_DEPENDENCIES) + @rm -f kms_render$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(kms_render_OBJECTS) $(kms_render_LDADD) $(LIBS) + +kms_setmode$(EXEEXT): $(kms_setmode_OBJECTS) $(kms_setmode_DEPENDENCIES) $(EXTRA_kms_setmode_DEPENDENCIES) + @rm -f kms_setmode$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(kms_setmode_OBJECTS) $(kms_setmode_LDADD) $(LIBS) + +kms_sink_crc_basic$(EXEEXT): $(kms_sink_crc_basic_OBJECTS) $(kms_sink_crc_basic_DEPENDENCIES) $(EXTRA_kms_sink_crc_basic_DEPENDENCIES) + @rm -f kms_sink_crc_basic$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(kms_sink_crc_basic_OBJECTS) $(kms_sink_crc_basic_LDADD) $(LIBS) + +pm_lpsp$(EXEEXT): $(pm_lpsp_OBJECTS) $(pm_lpsp_DEPENDENCIES) $(EXTRA_pm_lpsp_DEPENDENCIES) + @rm -f pm_lpsp$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pm_lpsp_OBJECTS) $(pm_lpsp_LDADD) $(LIBS) + +pm_psr$(EXEEXT): $(pm_psr_OBJECTS) $(pm_psr_DEPENDENCIES) $(EXTRA_pm_psr_DEPENDENCIES) + @rm -f pm_psr$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pm_psr_OBJECTS) $(pm_psr_LDADD) $(LIBS) + +pm_rc6_residency$(EXEEXT): $(pm_rc6_residency_OBJECTS) $(pm_rc6_residency_DEPENDENCIES) $(EXTRA_pm_rc6_residency_DEPENDENCIES) + @rm -f pm_rc6_residency$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pm_rc6_residency_OBJECTS) $(pm_rc6_residency_LDADD) $(LIBS) + +pm_rpm$(EXEEXT): $(pm_rpm_OBJECTS) $(pm_rpm_DEPENDENCIES) $(EXTRA_pm_rpm_DEPENDENCIES) + @rm -f pm_rpm$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pm_rpm_OBJECTS) $(pm_rpm_LDADD) $(LIBS) + +pm_rps$(EXEEXT): $(pm_rps_OBJECTS) $(pm_rps_DEPENDENCIES) $(EXTRA_pm_rps_DEPENDENCIES) + @rm -f pm_rps$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pm_rps_OBJECTS) $(pm_rps_LDADD) $(LIBS) + +prime_nv_api$(EXEEXT): $(prime_nv_api_OBJECTS) $(prime_nv_api_DEPENDENCIES) $(EXTRA_prime_nv_api_DEPENDENCIES) + @rm -f prime_nv_api$(EXEEXT) + $(AM_V_CCLD)$(prime_nv_api_LINK) $(prime_nv_api_OBJECTS) $(prime_nv_api_LDADD) $(LIBS) + +prime_nv_pcopy$(EXEEXT): $(prime_nv_pcopy_OBJECTS) $(prime_nv_pcopy_DEPENDENCIES) $(EXTRA_prime_nv_pcopy_DEPENDENCIES) + @rm -f prime_nv_pcopy$(EXEEXT) + $(AM_V_CCLD)$(prime_nv_pcopy_LINK) $(prime_nv_pcopy_OBJECTS) $(prime_nv_pcopy_LDADD) $(LIBS) + +prime_nv_test$(EXEEXT): $(prime_nv_test_OBJECTS) $(prime_nv_test_DEPENDENCIES) $(EXTRA_prime_nv_test_DEPENDENCIES) + @rm -f prime_nv_test$(EXEEXT) + $(AM_V_CCLD)$(prime_nv_test_LINK) $(prime_nv_test_OBJECTS) $(prime_nv_test_LDADD) $(LIBS) + +prime_self_import$(EXEEXT): $(prime_self_import_OBJECTS) $(prime_self_import_DEPENDENCIES) $(EXTRA_prime_self_import_DEPENDENCIES) + @rm -f prime_self_import$(EXEEXT) + $(AM_V_CCLD)$(prime_self_import_LINK) $(prime_self_import_OBJECTS) $(prime_self_import_LDADD) $(LIBS) + +prime_udl$(EXEEXT): $(prime_udl_OBJECTS) $(prime_udl_DEPENDENCIES) $(EXTRA_prime_udl_DEPENDENCIES) + @rm -f prime_udl$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(prime_udl_OBJECTS) $(prime_udl_LDADD) $(LIBS) + +template$(EXEEXT): $(template_OBJECTS) $(template_DEPENDENCIES) $(EXTRA_template_DEPENDENCIES) + @rm -f template$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(template_OBJECTS) $(template_LDADD) $(LIBS) + +testdisplay$(EXEEXT): $(testdisplay_OBJECTS) $(testdisplay_DEPENDENCIES) $(EXTRA_testdisplay_DEPENDENCIES) + @rm -f testdisplay$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(testdisplay_OBJECTS) $(testdisplay_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_get_client_auth.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_getclient.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_getstats.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_getversion.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddi_compute_wrpll.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drm_vma_limiter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drm_vma_limiter_cached.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drm_vma_limiter_cpu.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drm_vma_limiter_gtt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drv_hangman.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drv_suspend.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_alive.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_bad_address.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_bad_batch.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_bad_blit.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_bad_length.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_bad_reloc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_basic.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_caching.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_close_race-gem_close_race.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_concurrent_blit.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_cpu_reloc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_cs_prefetch.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_cs_tlb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_ctx_bad_destroy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_ctx_bad_exec.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_ctx_basic-gem_ctx_basic.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_ctx_create.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_ctx_exec.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_double_irq_loop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_dummy_reloc_loop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_evict_alignment.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_evict_everything.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_exec_bad_domains.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_exec_big.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_exec_blt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_exec_faulting_reloc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_exec_lut_handle.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_exec_nop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_exec_params.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_exec_parse.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_fd_exhaustion.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_fence_thrash-gem_fence_thrash.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_fenced_exec_thrash.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_flink.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_flink_race-gem_flink_race.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_gtt_cpu_tlb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_gtt_hog.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_gtt_speed.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_hang.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_hangcheck_forcewake.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_largeobject.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_linear_blits.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_lut_handle.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_madvise.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_media_fill.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_mmap.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_mmap_gtt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_mmap_offset_exhaustion.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_multi_bsd_sync_loop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_non_secure_batch.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_partial_pwrite_pread.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_persistent_relocs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_pin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_pipe_control_store_loop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_pread.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_pread_after_blit.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_pwrite.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_pwrite_pread.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_readwrite.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_reg_read.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_reloc_overflow.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_reloc_vs_gpu.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_render_copy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_render_copy_redux.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_render_linear_blits.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_render_tiled_blits.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_reset_stats.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_ring_sync_copy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_ring_sync_loop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_ringfill.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_seqno_wrap.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_set_tiling_vs_blt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_set_tiling_vs_gtt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_set_tiling_vs_pwrite.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_storedw_batches_loop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_storedw_loop_blt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_storedw_loop_bsd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_storedw_loop_render.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_storedw_loop_vebox.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_stress.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_threaded_access_tiled-gem_threaded_access_tiled.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_tiled_blits.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_tiled_fence_blits.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_tiled_partial_pwrite_pread.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_tiled_pread.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_tiled_pread_pwrite.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_tiled_swapping-gem_tiled_swapping.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_tiling_max_stride.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_unfence_active_buffers.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_unref_active_buffers.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_userptr_blits.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_wait_render_timeout.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gem_write_read_ring_switch.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen3_mixed_blits.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen3_render_linear_blits.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen3_render_mixed_blits.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen3_render_tiledx_blits.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen3_render_tiledy_blits.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen7_forcewake_mt-gen7_forcewake_mt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/igt_fork_helper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/igt_list_only.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/igt_no_exit.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/igt_no_exit_list_only.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/igt_no_subtest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/igt_simulation.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kms_addfb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kms_cursor_crc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kms_fbc_crc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kms_fence_pin_leak.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kms_flip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kms_flip_tiling.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kms_mmio_vs_cs_flip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kms_pipe_crc_basic.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kms_plane.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kms_render.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kms_setmode.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kms_sink_crc_basic.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pm_lpsp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pm_psr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pm_rc6_residency.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pm_rpm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pm_rps.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prime_nv_api-prime_nv_api.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prime_nv_pcopy-prime_nv_pcopy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prime_nv_test-prime_nv_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prime_self_import-prime_self_import.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prime_udl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/template.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testdisplay.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testdisplay_hotplug.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +gem_close_race-gem_close_race.o: gem_close_race.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_close_race_CFLAGS) $(CFLAGS) -MT gem_close_race-gem_close_race.o -MD -MP -MF $(DEPDIR)/gem_close_race-gem_close_race.Tpo -c -o gem_close_race-gem_close_race.o `test -f 'gem_close_race.c' || echo '$(srcdir)/'`gem_close_race.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gem_close_race-gem_close_race.Tpo $(DEPDIR)/gem_close_race-gem_close_race.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gem_close_race.c' object='gem_close_race-gem_close_race.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_close_race_CFLAGS) $(CFLAGS) -c -o gem_close_race-gem_close_race.o `test -f 'gem_close_race.c' || echo '$(srcdir)/'`gem_close_race.c + +gem_close_race-gem_close_race.obj: gem_close_race.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_close_race_CFLAGS) $(CFLAGS) -MT gem_close_race-gem_close_race.obj -MD -MP -MF $(DEPDIR)/gem_close_race-gem_close_race.Tpo -c -o gem_close_race-gem_close_race.obj `if test -f 'gem_close_race.c'; then $(CYGPATH_W) 'gem_close_race.c'; else $(CYGPATH_W) '$(srcdir)/gem_close_race.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gem_close_race-gem_close_race.Tpo $(DEPDIR)/gem_close_race-gem_close_race.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gem_close_race.c' object='gem_close_race-gem_close_race.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_close_race_CFLAGS) $(CFLAGS) -c -o gem_close_race-gem_close_race.obj `if test -f 'gem_close_race.c'; then $(CYGPATH_W) 'gem_close_race.c'; else $(CYGPATH_W) '$(srcdir)/gem_close_race.c'; fi` + +gem_ctx_basic-gem_ctx_basic.o: gem_ctx_basic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_ctx_basic_CFLAGS) $(CFLAGS) -MT gem_ctx_basic-gem_ctx_basic.o -MD -MP -MF $(DEPDIR)/gem_ctx_basic-gem_ctx_basic.Tpo -c -o gem_ctx_basic-gem_ctx_basic.o `test -f 'gem_ctx_basic.c' || echo '$(srcdir)/'`gem_ctx_basic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gem_ctx_basic-gem_ctx_basic.Tpo $(DEPDIR)/gem_ctx_basic-gem_ctx_basic.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gem_ctx_basic.c' object='gem_ctx_basic-gem_ctx_basic.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_ctx_basic_CFLAGS) $(CFLAGS) -c -o gem_ctx_basic-gem_ctx_basic.o `test -f 'gem_ctx_basic.c' || echo '$(srcdir)/'`gem_ctx_basic.c + +gem_ctx_basic-gem_ctx_basic.obj: gem_ctx_basic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_ctx_basic_CFLAGS) $(CFLAGS) -MT gem_ctx_basic-gem_ctx_basic.obj -MD -MP -MF $(DEPDIR)/gem_ctx_basic-gem_ctx_basic.Tpo -c -o gem_ctx_basic-gem_ctx_basic.obj `if test -f 'gem_ctx_basic.c'; then $(CYGPATH_W) 'gem_ctx_basic.c'; else $(CYGPATH_W) '$(srcdir)/gem_ctx_basic.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gem_ctx_basic-gem_ctx_basic.Tpo $(DEPDIR)/gem_ctx_basic-gem_ctx_basic.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gem_ctx_basic.c' object='gem_ctx_basic-gem_ctx_basic.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_ctx_basic_CFLAGS) $(CFLAGS) -c -o gem_ctx_basic-gem_ctx_basic.obj `if test -f 'gem_ctx_basic.c'; then $(CYGPATH_W) 'gem_ctx_basic.c'; else $(CYGPATH_W) '$(srcdir)/gem_ctx_basic.c'; fi` + +gem_fence_thrash-gem_fence_thrash.o: gem_fence_thrash.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_fence_thrash_CFLAGS) $(CFLAGS) -MT gem_fence_thrash-gem_fence_thrash.o -MD -MP -MF $(DEPDIR)/gem_fence_thrash-gem_fence_thrash.Tpo -c -o gem_fence_thrash-gem_fence_thrash.o `test -f 'gem_fence_thrash.c' || echo '$(srcdir)/'`gem_fence_thrash.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gem_fence_thrash-gem_fence_thrash.Tpo $(DEPDIR)/gem_fence_thrash-gem_fence_thrash.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gem_fence_thrash.c' object='gem_fence_thrash-gem_fence_thrash.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_fence_thrash_CFLAGS) $(CFLAGS) -c -o gem_fence_thrash-gem_fence_thrash.o `test -f 'gem_fence_thrash.c' || echo '$(srcdir)/'`gem_fence_thrash.c + +gem_fence_thrash-gem_fence_thrash.obj: gem_fence_thrash.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_fence_thrash_CFLAGS) $(CFLAGS) -MT gem_fence_thrash-gem_fence_thrash.obj -MD -MP -MF $(DEPDIR)/gem_fence_thrash-gem_fence_thrash.Tpo -c -o gem_fence_thrash-gem_fence_thrash.obj `if test -f 'gem_fence_thrash.c'; then $(CYGPATH_W) 'gem_fence_thrash.c'; else $(CYGPATH_W) '$(srcdir)/gem_fence_thrash.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gem_fence_thrash-gem_fence_thrash.Tpo $(DEPDIR)/gem_fence_thrash-gem_fence_thrash.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gem_fence_thrash.c' object='gem_fence_thrash-gem_fence_thrash.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_fence_thrash_CFLAGS) $(CFLAGS) -c -o gem_fence_thrash-gem_fence_thrash.obj `if test -f 'gem_fence_thrash.c'; then $(CYGPATH_W) 'gem_fence_thrash.c'; else $(CYGPATH_W) '$(srcdir)/gem_fence_thrash.c'; fi` + +gem_flink_race-gem_flink_race.o: gem_flink_race.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_flink_race_CFLAGS) $(CFLAGS) -MT gem_flink_race-gem_flink_race.o -MD -MP -MF $(DEPDIR)/gem_flink_race-gem_flink_race.Tpo -c -o gem_flink_race-gem_flink_race.o `test -f 'gem_flink_race.c' || echo '$(srcdir)/'`gem_flink_race.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gem_flink_race-gem_flink_race.Tpo $(DEPDIR)/gem_flink_race-gem_flink_race.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gem_flink_race.c' object='gem_flink_race-gem_flink_race.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_flink_race_CFLAGS) $(CFLAGS) -c -o gem_flink_race-gem_flink_race.o `test -f 'gem_flink_race.c' || echo '$(srcdir)/'`gem_flink_race.c + +gem_flink_race-gem_flink_race.obj: gem_flink_race.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_flink_race_CFLAGS) $(CFLAGS) -MT gem_flink_race-gem_flink_race.obj -MD -MP -MF $(DEPDIR)/gem_flink_race-gem_flink_race.Tpo -c -o gem_flink_race-gem_flink_race.obj `if test -f 'gem_flink_race.c'; then $(CYGPATH_W) 'gem_flink_race.c'; else $(CYGPATH_W) '$(srcdir)/gem_flink_race.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gem_flink_race-gem_flink_race.Tpo $(DEPDIR)/gem_flink_race-gem_flink_race.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gem_flink_race.c' object='gem_flink_race-gem_flink_race.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_flink_race_CFLAGS) $(CFLAGS) -c -o gem_flink_race-gem_flink_race.obj `if test -f 'gem_flink_race.c'; then $(CYGPATH_W) 'gem_flink_race.c'; else $(CYGPATH_W) '$(srcdir)/gem_flink_race.c'; fi` + +gem_threaded_access_tiled-gem_threaded_access_tiled.o: gem_threaded_access_tiled.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_threaded_access_tiled_CFLAGS) $(CFLAGS) -MT gem_threaded_access_tiled-gem_threaded_access_tiled.o -MD -MP -MF $(DEPDIR)/gem_threaded_access_tiled-gem_threaded_access_tiled.Tpo -c -o gem_threaded_access_tiled-gem_threaded_access_tiled.o `test -f 'gem_threaded_access_tiled.c' || echo '$(srcdir)/'`gem_threaded_access_tiled.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gem_threaded_access_tiled-gem_threaded_access_tiled.Tpo $(DEPDIR)/gem_threaded_access_tiled-gem_threaded_access_tiled.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gem_threaded_access_tiled.c' object='gem_threaded_access_tiled-gem_threaded_access_tiled.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_threaded_access_tiled_CFLAGS) $(CFLAGS) -c -o gem_threaded_access_tiled-gem_threaded_access_tiled.o `test -f 'gem_threaded_access_tiled.c' || echo '$(srcdir)/'`gem_threaded_access_tiled.c + +gem_threaded_access_tiled-gem_threaded_access_tiled.obj: gem_threaded_access_tiled.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_threaded_access_tiled_CFLAGS) $(CFLAGS) -MT gem_threaded_access_tiled-gem_threaded_access_tiled.obj -MD -MP -MF $(DEPDIR)/gem_threaded_access_tiled-gem_threaded_access_tiled.Tpo -c -o gem_threaded_access_tiled-gem_threaded_access_tiled.obj `if test -f 'gem_threaded_access_tiled.c'; then $(CYGPATH_W) 'gem_threaded_access_tiled.c'; else $(CYGPATH_W) '$(srcdir)/gem_threaded_access_tiled.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gem_threaded_access_tiled-gem_threaded_access_tiled.Tpo $(DEPDIR)/gem_threaded_access_tiled-gem_threaded_access_tiled.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gem_threaded_access_tiled.c' object='gem_threaded_access_tiled-gem_threaded_access_tiled.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_threaded_access_tiled_CFLAGS) $(CFLAGS) -c -o gem_threaded_access_tiled-gem_threaded_access_tiled.obj `if test -f 'gem_threaded_access_tiled.c'; then $(CYGPATH_W) 'gem_threaded_access_tiled.c'; else $(CYGPATH_W) '$(srcdir)/gem_threaded_access_tiled.c'; fi` + +gem_tiled_swapping-gem_tiled_swapping.o: gem_tiled_swapping.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_tiled_swapping_CFLAGS) $(CFLAGS) -MT gem_tiled_swapping-gem_tiled_swapping.o -MD -MP -MF $(DEPDIR)/gem_tiled_swapping-gem_tiled_swapping.Tpo -c -o gem_tiled_swapping-gem_tiled_swapping.o `test -f 'gem_tiled_swapping.c' || echo '$(srcdir)/'`gem_tiled_swapping.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gem_tiled_swapping-gem_tiled_swapping.Tpo $(DEPDIR)/gem_tiled_swapping-gem_tiled_swapping.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gem_tiled_swapping.c' object='gem_tiled_swapping-gem_tiled_swapping.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_tiled_swapping_CFLAGS) $(CFLAGS) -c -o gem_tiled_swapping-gem_tiled_swapping.o `test -f 'gem_tiled_swapping.c' || echo '$(srcdir)/'`gem_tiled_swapping.c + +gem_tiled_swapping-gem_tiled_swapping.obj: gem_tiled_swapping.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_tiled_swapping_CFLAGS) $(CFLAGS) -MT gem_tiled_swapping-gem_tiled_swapping.obj -MD -MP -MF $(DEPDIR)/gem_tiled_swapping-gem_tiled_swapping.Tpo -c -o gem_tiled_swapping-gem_tiled_swapping.obj `if test -f 'gem_tiled_swapping.c'; then $(CYGPATH_W) 'gem_tiled_swapping.c'; else $(CYGPATH_W) '$(srcdir)/gem_tiled_swapping.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gem_tiled_swapping-gem_tiled_swapping.Tpo $(DEPDIR)/gem_tiled_swapping-gem_tiled_swapping.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gem_tiled_swapping.c' object='gem_tiled_swapping-gem_tiled_swapping.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gem_tiled_swapping_CFLAGS) $(CFLAGS) -c -o gem_tiled_swapping-gem_tiled_swapping.obj `if test -f 'gem_tiled_swapping.c'; then $(CYGPATH_W) 'gem_tiled_swapping.c'; else $(CYGPATH_W) '$(srcdir)/gem_tiled_swapping.c'; fi` + +gen7_forcewake_mt-gen7_forcewake_mt.o: gen7_forcewake_mt.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gen7_forcewake_mt_CFLAGS) $(CFLAGS) -MT gen7_forcewake_mt-gen7_forcewake_mt.o -MD -MP -MF $(DEPDIR)/gen7_forcewake_mt-gen7_forcewake_mt.Tpo -c -o gen7_forcewake_mt-gen7_forcewake_mt.o `test -f 'gen7_forcewake_mt.c' || echo '$(srcdir)/'`gen7_forcewake_mt.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gen7_forcewake_mt-gen7_forcewake_mt.Tpo $(DEPDIR)/gen7_forcewake_mt-gen7_forcewake_mt.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gen7_forcewake_mt.c' object='gen7_forcewake_mt-gen7_forcewake_mt.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gen7_forcewake_mt_CFLAGS) $(CFLAGS) -c -o gen7_forcewake_mt-gen7_forcewake_mt.o `test -f 'gen7_forcewake_mt.c' || echo '$(srcdir)/'`gen7_forcewake_mt.c + +gen7_forcewake_mt-gen7_forcewake_mt.obj: gen7_forcewake_mt.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gen7_forcewake_mt_CFLAGS) $(CFLAGS) -MT gen7_forcewake_mt-gen7_forcewake_mt.obj -MD -MP -MF $(DEPDIR)/gen7_forcewake_mt-gen7_forcewake_mt.Tpo -c -o gen7_forcewake_mt-gen7_forcewake_mt.obj `if test -f 'gen7_forcewake_mt.c'; then $(CYGPATH_W) 'gen7_forcewake_mt.c'; else $(CYGPATH_W) '$(srcdir)/gen7_forcewake_mt.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gen7_forcewake_mt-gen7_forcewake_mt.Tpo $(DEPDIR)/gen7_forcewake_mt-gen7_forcewake_mt.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gen7_forcewake_mt.c' object='gen7_forcewake_mt-gen7_forcewake_mt.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gen7_forcewake_mt_CFLAGS) $(CFLAGS) -c -o gen7_forcewake_mt-gen7_forcewake_mt.obj `if test -f 'gen7_forcewake_mt.c'; then $(CYGPATH_W) 'gen7_forcewake_mt.c'; else $(CYGPATH_W) '$(srcdir)/gen7_forcewake_mt.c'; fi` + +prime_nv_api-prime_nv_api.o: prime_nv_api.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(prime_nv_api_CFLAGS) $(CFLAGS) -MT prime_nv_api-prime_nv_api.o -MD -MP -MF $(DEPDIR)/prime_nv_api-prime_nv_api.Tpo -c -o prime_nv_api-prime_nv_api.o `test -f 'prime_nv_api.c' || echo '$(srcdir)/'`prime_nv_api.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/prime_nv_api-prime_nv_api.Tpo $(DEPDIR)/prime_nv_api-prime_nv_api.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='prime_nv_api.c' object='prime_nv_api-prime_nv_api.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(prime_nv_api_CFLAGS) $(CFLAGS) -c -o prime_nv_api-prime_nv_api.o `test -f 'prime_nv_api.c' || echo '$(srcdir)/'`prime_nv_api.c + +prime_nv_api-prime_nv_api.obj: prime_nv_api.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(prime_nv_api_CFLAGS) $(CFLAGS) -MT prime_nv_api-prime_nv_api.obj -MD -MP -MF $(DEPDIR)/prime_nv_api-prime_nv_api.Tpo -c -o prime_nv_api-prime_nv_api.obj `if test -f 'prime_nv_api.c'; then $(CYGPATH_W) 'prime_nv_api.c'; else $(CYGPATH_W) '$(srcdir)/prime_nv_api.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/prime_nv_api-prime_nv_api.Tpo $(DEPDIR)/prime_nv_api-prime_nv_api.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='prime_nv_api.c' object='prime_nv_api-prime_nv_api.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(prime_nv_api_CFLAGS) $(CFLAGS) -c -o prime_nv_api-prime_nv_api.obj `if test -f 'prime_nv_api.c'; then $(CYGPATH_W) 'prime_nv_api.c'; else $(CYGPATH_W) '$(srcdir)/prime_nv_api.c'; fi` + +prime_nv_pcopy-prime_nv_pcopy.o: prime_nv_pcopy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(prime_nv_pcopy_CFLAGS) $(CFLAGS) -MT prime_nv_pcopy-prime_nv_pcopy.o -MD -MP -MF $(DEPDIR)/prime_nv_pcopy-prime_nv_pcopy.Tpo -c -o prime_nv_pcopy-prime_nv_pcopy.o `test -f 'prime_nv_pcopy.c' || echo '$(srcdir)/'`prime_nv_pcopy.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/prime_nv_pcopy-prime_nv_pcopy.Tpo $(DEPDIR)/prime_nv_pcopy-prime_nv_pcopy.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='prime_nv_pcopy.c' object='prime_nv_pcopy-prime_nv_pcopy.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(prime_nv_pcopy_CFLAGS) $(CFLAGS) -c -o prime_nv_pcopy-prime_nv_pcopy.o `test -f 'prime_nv_pcopy.c' || echo '$(srcdir)/'`prime_nv_pcopy.c + +prime_nv_pcopy-prime_nv_pcopy.obj: prime_nv_pcopy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(prime_nv_pcopy_CFLAGS) $(CFLAGS) -MT prime_nv_pcopy-prime_nv_pcopy.obj -MD -MP -MF $(DEPDIR)/prime_nv_pcopy-prime_nv_pcopy.Tpo -c -o prime_nv_pcopy-prime_nv_pcopy.obj `if test -f 'prime_nv_pcopy.c'; then $(CYGPATH_W) 'prime_nv_pcopy.c'; else $(CYGPATH_W) '$(srcdir)/prime_nv_pcopy.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/prime_nv_pcopy-prime_nv_pcopy.Tpo $(DEPDIR)/prime_nv_pcopy-prime_nv_pcopy.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='prime_nv_pcopy.c' object='prime_nv_pcopy-prime_nv_pcopy.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(prime_nv_pcopy_CFLAGS) $(CFLAGS) -c -o prime_nv_pcopy-prime_nv_pcopy.obj `if test -f 'prime_nv_pcopy.c'; then $(CYGPATH_W) 'prime_nv_pcopy.c'; else $(CYGPATH_W) '$(srcdir)/prime_nv_pcopy.c'; fi` + +prime_nv_test-prime_nv_test.o: prime_nv_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(prime_nv_test_CFLAGS) $(CFLAGS) -MT prime_nv_test-prime_nv_test.o -MD -MP -MF $(DEPDIR)/prime_nv_test-prime_nv_test.Tpo -c -o prime_nv_test-prime_nv_test.o `test -f 'prime_nv_test.c' || echo '$(srcdir)/'`prime_nv_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/prime_nv_test-prime_nv_test.Tpo $(DEPDIR)/prime_nv_test-prime_nv_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='prime_nv_test.c' object='prime_nv_test-prime_nv_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(prime_nv_test_CFLAGS) $(CFLAGS) -c -o prime_nv_test-prime_nv_test.o `test -f 'prime_nv_test.c' || echo '$(srcdir)/'`prime_nv_test.c + +prime_nv_test-prime_nv_test.obj: prime_nv_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(prime_nv_test_CFLAGS) $(CFLAGS) -MT prime_nv_test-prime_nv_test.obj -MD -MP -MF $(DEPDIR)/prime_nv_test-prime_nv_test.Tpo -c -o prime_nv_test-prime_nv_test.obj `if test -f 'prime_nv_test.c'; then $(CYGPATH_W) 'prime_nv_test.c'; else $(CYGPATH_W) '$(srcdir)/prime_nv_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/prime_nv_test-prime_nv_test.Tpo $(DEPDIR)/prime_nv_test-prime_nv_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='prime_nv_test.c' object='prime_nv_test-prime_nv_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(prime_nv_test_CFLAGS) $(CFLAGS) -c -o prime_nv_test-prime_nv_test.obj `if test -f 'prime_nv_test.c'; then $(CYGPATH_W) 'prime_nv_test.c'; else $(CYGPATH_W) '$(srcdir)/prime_nv_test.c'; fi` + +prime_self_import-prime_self_import.o: prime_self_import.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(prime_self_import_CFLAGS) $(CFLAGS) -MT prime_self_import-prime_self_import.o -MD -MP -MF $(DEPDIR)/prime_self_import-prime_self_import.Tpo -c -o prime_self_import-prime_self_import.o `test -f 'prime_self_import.c' || echo '$(srcdir)/'`prime_self_import.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/prime_self_import-prime_self_import.Tpo $(DEPDIR)/prime_self_import-prime_self_import.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='prime_self_import.c' object='prime_self_import-prime_self_import.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(prime_self_import_CFLAGS) $(CFLAGS) -c -o prime_self_import-prime_self_import.o `test -f 'prime_self_import.c' || echo '$(srcdir)/'`prime_self_import.c + +prime_self_import-prime_self_import.obj: prime_self_import.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(prime_self_import_CFLAGS) $(CFLAGS) -MT prime_self_import-prime_self_import.obj -MD -MP -MF $(DEPDIR)/prime_self_import-prime_self_import.Tpo -c -o prime_self_import-prime_self_import.obj `if test -f 'prime_self_import.c'; then $(CYGPATH_W) 'prime_self_import.c'; else $(CYGPATH_W) '$(srcdir)/prime_self_import.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/prime_self_import-prime_self_import.Tpo $(DEPDIR)/prime_self_import-prime_self_import.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='prime_self_import.c' object='prime_self_import-prime_self_import.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(prime_self_import_CFLAGS) $(CFLAGS) -c -o prime_self_import-prime_self_import.obj `if test -f 'prime_self_import.c'; then $(CYGPATH_W) 'prime_self_import.c'; else $(CYGPATH_W) '$(srcdir)/prime_self_import.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + else \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +igt_no_exit.log: igt_no_exit$(EXEEXT) + @p='igt_no_exit$(EXEEXT)'; \ + b='igt_no_exit'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +igt_no_exit_list_only.log: igt_no_exit_list_only$(EXEEXT) + @p='igt_no_exit_list_only$(EXEEXT)'; \ + b='igt_no_exit_list_only'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +igt_fork_helper.log: igt_fork_helper$(EXEEXT) + @p='igt_fork_helper$(EXEEXT)'; \ + b='igt_fork_helper'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +igt_list_only.log: igt_list_only$(EXEEXT) + @p='igt_list_only$(EXEEXT)'; \ + b='igt_list_only'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +igt_no_subtest.log: igt_no_subtest$(EXEEXT) + @p='igt_no_subtest$(EXEEXT)'; \ + b='igt_no_subtest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +igt_simulation.log: igt_simulation$(EXEEXT) + @p='igt_simulation$(EXEEXT)'; \ + b='igt_simulation'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +@BUILD_TESTS_FALSE@all-local: +all-am: Makefile $(PROGRAMS) all-local +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am all-local check check-TESTS \ + check-am clean clean-generic clean-libtool \ + clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am recheck tags tags-am uninstall \ + uninstall-am + + +@BUILD_TESTS_TRUE@all-local: single-tests.txt multi-tests.txt + +@BUILD_TESTS_TRUE@list-single-tests: +@BUILD_TESTS_TRUE@ @echo TESTLIST +@BUILD_TESTS_TRUE@ @echo ${single_kernel_tests} +@BUILD_TESTS_TRUE@ @echo END TESTLIST + +@BUILD_TESTS_TRUE@list-multi-tests: +@BUILD_TESTS_TRUE@ @echo TESTLIST +@BUILD_TESTS_TRUE@ @echo ${multi_kernel_tests} +@BUILD_TESTS_TRUE@ @echo END TESTLIST + +@BUILD_TESTS_TRUE@single-tests.txt: Makefile.sources +@BUILD_TESTS_TRUE@ @echo TESTLIST > $@ +@BUILD_TESTS_TRUE@ @echo ${single_kernel_tests} >> $@ +@BUILD_TESTS_TRUE@ @echo END TESTLIST >> $@ + +@BUILD_TESTS_TRUE@multi-tests.txt: Makefile.sources +@BUILD_TESTS_TRUE@ @echo TESTLIST > $@ +@BUILD_TESTS_TRUE@ @echo ${multi_kernel_tests} >> $@ +@BUILD_TESTS_TRUE@ @echo END TESTLIST >> $@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/Makefile.sources b/tests/Makefile.sources new file mode 100644 index 00000000..e4c23b3f --- /dev/null +++ b/tests/Makefile.sources @@ -0,0 +1,237 @@ +noinst_PROGRAMS = \ + gem_alive \ + gem_stress \ + ddi_compute_wrpll \ + $(TESTS_progs) \ + $(TESTS_progs_M) \ + $(HANG) \ + $(TESTS_testsuite) \ + $(NULL) + +NOUVEAU_TESTS_M = \ + prime_nv_api \ + prime_nv_pcopy \ + prime_nv_test \ + $(NULL) + +TESTS_progs_M = \ + core_get_client_auth \ + drv_suspend \ + drv_hangman \ + gem_bad_reloc \ + gem_basic \ + gem_caching \ + gem_close_race \ + gem_concurrent_blit \ + gem_cs_tlb \ + gem_ctx_bad_exec \ + gem_ctx_exec \ + gem_dummy_reloc_loop \ + gem_evict_alignment \ + gem_evict_everything \ + gem_exec_bad_domains \ + gem_exec_faulting_reloc \ + gem_exec_nop \ + gem_exec_params \ + gem_exec_parse \ + gem_fenced_exec_thrash \ + gem_fence_thrash \ + gem_flink \ + gem_flink_race \ + gem_linear_blits \ + gem_madvise \ + gem_mmap \ + gem_mmap_gtt \ + gem_partial_pwrite_pread \ + gem_persistent_relocs \ + gem_pipe_control_store_loop \ + gem_pread \ + gem_pread_after_blit \ + gem_pwrite \ + gem_pwrite_pread \ + gem_readwrite \ + gem_reloc_overflow \ + gem_reloc_vs_gpu \ + gem_reset_stats \ + gem_ringfill \ + gem_set_tiling_vs_blt \ + gem_storedw_batches_loop \ + gem_tiled_blits \ + gem_tiled_partial_pwrite_pread \ + gem_write_read_ring_switch \ + kms_addfb \ + kms_cursor_crc \ + kms_fbc_crc \ + kms_flip \ + kms_flip_tiling \ + kms_mmio_vs_cs_flip \ + kms_pipe_crc_basic \ + kms_plane \ + kms_render \ + kms_setmode \ + pm_lpsp \ + pm_rpm \ + pm_rps \ + prime_self_import \ + template \ + $(NULL) + +TESTS_progs = \ + core_getclient \ + core_getstats \ + core_getversion \ + drm_vma_limiter \ + drm_vma_limiter_cached \ + drm_vma_limiter_cpu \ + drm_vma_limiter_gtt \ + gem_bad_length \ + gem_cpu_reloc \ + gem_cs_prefetch \ + gem_ctx_bad_destroy \ + gem_ctx_basic \ + gem_ctx_create \ + gem_double_irq_loop \ + gem_exec_big \ + gem_exec_blt \ + gem_exec_lut_handle \ + gem_fd_exhaustion \ + gem_gtt_cpu_tlb \ + gem_gtt_hog \ + gem_gtt_speed \ + gem_hangcheck_forcewake \ + gem_largeobject \ + gem_lut_handle \ + gem_mmap_offset_exhaustion \ + gem_media_fill \ + gem_pin \ + gem_reg_read \ + gem_render_copy \ + gem_render_copy_redux \ + gem_render_linear_blits \ + gem_render_tiled_blits \ + gem_ring_sync_copy \ + gem_ring_sync_loop \ + gem_multi_bsd_sync_loop \ + gem_seqno_wrap \ + gem_set_tiling_vs_gtt \ + gem_set_tiling_vs_pwrite \ + gem_storedw_loop_blt \ + gem_storedw_loop_bsd \ + gem_storedw_loop_render \ + gem_storedw_loop_vebox \ + gem_threaded_access_tiled \ + gem_tiled_fence_blits \ + gem_tiled_pread \ + gem_tiled_pread_pwrite \ + gem_tiled_swapping \ + gem_tiling_max_stride \ + gem_unfence_active_buffers \ + gem_unref_active_buffers \ + gem_userptr_blits \ + gem_wait_render_timeout \ + gen3_mixed_blits \ + gen3_render_linear_blits \ + gen3_render_mixed_blits \ + gen3_render_tiledx_blits \ + gen3_render_tiledy_blits \ + gen7_forcewake_mt \ + kms_sink_crc_basic \ + kms_fence_pin_leak \ + pm_psr \ + pm_rc6_residency \ + prime_udl \ + $(NULL) + +# IMPORTANT: The ZZ_ tests need to be run last! +# ... and make can't deal with inlined comments ... +TESTS_scripts_M = \ + $(NULL) + +TESTS_scripts = \ + debugfs_emon_crash \ + drv_debugfs_reader \ + drv_missed_irq_hang \ + drv_module_reload \ + kms_sysfs_edid_timing \ + sysfs_l3_parity \ + test_rte_check \ + tools_test \ + $(NULL) + +# This target contains testcases which support automagic subtest enumeration +# from the piglit testrunner with --list-subtests and running individual +# subtests with --run-subtest <testname> +# +# Your testcase should probably use an igt_main and igt_fixture and should have +# a pile of igt_subtest blocks. +multi_kernel_tests = \ + $(TESTS_progs_M) \ + $(TESTS_scripts_M) \ + $(NULL) + +# This target is for simple testcase which don't expose any subtest. +# +# Your testcase should probably use igt_simple_main, but none of the other magic +# blocks like igt_fixture or igt_subtest. +single_kernel_tests = \ + $(TESTS_progs) \ + $(TESTS_scripts) \ + $(NULL) + +kernel_tests = \ + $(single_kernel_tests) \ + $(multi_kernel_tests) \ + $(NULL) + +TESTS_testsuite = \ + igt_no_exit \ + igt_no_exit_list_only \ + igt_fork_helper \ + igt_list_only \ + igt_no_subtest \ + igt_simulation \ + $(NULL) + +TESTS = \ + $(TESTS_testsuite) \ + $(NULL) + +# Test that exercise specific asserts in the test framework library and are +# hence expected to fail. +XFAIL_TESTS = \ + igt_no_exit \ + igt_no_exit_list_only \ + igt_no_subtest \ + $(NULL) + +# IMPORTANT: These tests here are all disabled because the result in sometime +# unrecoverable gpu hangs. Don't put real testcases here. +HANG = \ + gem_bad_batch \ + gem_hang \ + gem_bad_blit \ + gem_bad_address \ + gem_non_secure_batch \ + $(NULL) + +scripts = \ + check_drm_clients \ + ddx_intel_after_fbdev \ + debugfs_wedged \ + drm_lib.sh \ + $(NULL) + +IMAGES = pass.png 1080p-left.png 1080p-right.png + +testdisplay_SOURCES = \ + testdisplay.c \ + testdisplay.h \ + testdisplay_hotplug.c \ + $(NULL) + +TESTS_progs += testdisplay + +common_files = \ + eviction_common.c \ + $(NULL) + diff --git a/tests/ZZ_check_dmesg b/tests/ZZ_check_dmesg deleted file mode 100755 index e28ba35f..00000000 --- a/tests/ZZ_check_dmesg +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -if dmesg | grep '\*ERROR\*' > /dev/null ; then - echo "DRM_ERROR dirt in dmesg" - exit 1 -fi - -if dmesg | grep -- '------\[ cut here \]----' > /dev/null ; then - echo "found a backtrace in dmesg" - exit 1 -fi diff --git a/tests/ZZ_hangman b/tests/ZZ_hangman deleted file mode 100755 index b8f4a682..00000000 --- a/tests/ZZ_hangman +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash -# -# Testcase: Simulate gpu hang -# -# This check uses the stop_rings facility to exercise the gpu hang code. -# by reading /sys/kernel/debug/dri/0/i915_emon_status too quickly -# - -SOURCE_DIR="$( dirname "${BASH_SOURCE[0]}" )" -. $SOURCE_DIR/drm_lib.sh - -oldpath=`pwd` - -cd $i915_path - -if [ ! -f i915_ring_stop ] ; then - echo "kernel doesn't support ring stopping" - exit 77 -fi - -if cat i915_error_state | grep -v "no error state collected" > /dev/null ; then - echo "gpu hang dectected" - exit 1 -fi - -# stop rings -echo 0xf > i915_ring_stop -echo "rings stopped" - -(cd $oldpath; $SOURCE_DIR/gem_exec_nop) > /dev/null - -if cat i915_error_state | grep -v "no error state collected" > /dev/null ; then - echo "gpu hang correctly dectected" -else - echo "gpu hang not dectected" - exit 2 -fi - -# clear error state -echo > i915_error_state - -exit 0 diff --git a/tests/core_get_client_auth.c b/tests/core_get_client_auth.c new file mode 100644 index 00000000..eef97e02 --- /dev/null +++ b/tests/core_get_client_auth.c @@ -0,0 +1,100 @@ +/* + * Copyright © 2012,2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Daniel Vetter <daniel.vetter@ffwll.ch> + * + * Based upon code from libva/va/drm/va_drm_auth.c: + */ + +/* + * Testcase: Check that the hollowed-out get_client ioctl still works for libva + * + * Oh dear, libva, why do you do such funny things? + */ + +#define _GNU_SOURCE +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +# include <sys/syscall.h> + +#include "drm.h" +#include "ioctl_wrappers.h" +#include "drmtest.h" + +/* Checks whether the thread id is the current thread */ +static bool +is_local_tid(pid_t tid) +{ +#ifndef ANDROID + /* On Linux systems, drmGetClient() would return the thread ID + instead of the actual process ID */ + return syscall(SYS_gettid) == tid; +#else + return gettid() == tid; +#endif +} + + +static bool check_auth(int fd) +{ + pid_t client_pid; + int i, auth, pid, uid; + unsigned long magic, iocs; + bool is_authenticated = false; + + client_pid = getpid(); + for (i = 0; !is_authenticated; i++) { + if (drmGetClient(fd, i, &auth, &pid, &uid, &magic, &iocs) != 0) + break; + is_authenticated = auth && (pid == client_pid || is_local_tid(pid)); + } + return is_authenticated; +} + + +igt_main +{ + /* root (which we run igt as) should always be authenticated */ + igt_subtest("simple") { + int fd = drm_open_any(); + + igt_assert(check_auth(fd) == true); + + close(fd); + } + + igt_subtest("master-drop") { + int fd = drm_open_any(); + int fd2 = drm_open_any(); + + igt_assert(check_auth(fd2) == true); + + close(fd); + + igt_assert(check_auth(fd2) == true); + + close(fd2); + } +} diff --git a/tests/getclient.c b/tests/core_getclient.c index 481ce119..ed46e519 100644 --- a/tests/getclient.c +++ b/tests/core_getclient.c @@ -27,12 +27,15 @@ #include <limits.h> #include <sys/ioctl.h> +#include <stdlib.h> +#include <errno.h> + #include "drmtest.h" /** * Checks DRM_IOCTL_GET_CLIENT. */ -int main(int argc, char **argv) +igt_simple_main { int fd, ret; drm_client_t client; @@ -45,7 +48,7 @@ int main(int argc, char **argv) */ client.idx = 0; ret = ioctl(fd, DRM_IOCTL_GET_CLIENT, &client); - assert(ret == 0); + igt_assert(ret == 0); /* Look for some absurd client index and make sure it's invalid. * The DRM drivers currently always return data, so the user has @@ -54,8 +57,7 @@ int main(int argc, char **argv) */ client.idx = 0x7fffffff; ret = ioctl(fd, DRM_IOCTL_GET_CLIENT, &client); - assert(ret == -1 && errno == EINVAL); + igt_assert(ret == -1 && errno == EINVAL); close(fd); - return 0; } diff --git a/tests/getstats.c b/tests/core_getstats.c index 8a7d2999..1e2c5651 100644 --- a/tests/getstats.c +++ b/tests/core_getstats.c @@ -27,6 +27,11 @@ #include <limits.h> #include <sys/ioctl.h> +#include <sys/types.h> + +#include <drm.h> + +#include "igt_core.h" #include "drmtest.h" /** @@ -35,7 +40,7 @@ * I don't care too much about the actual contents, just that the kernel * doesn't crash. */ -int main(int argc, char **argv) +igt_simple_main { int fd, ret; drm_stats_t stats; @@ -43,8 +48,7 @@ int main(int argc, char **argv) fd = drm_open_any(); ret = ioctl(fd, DRM_IOCTL_GET_STATS, &stats); - assert(ret == 0); + igt_assert(ret == 0); close(fd); - return 0; } diff --git a/tests/getversion.c b/tests/core_getversion.c index 4847e796..7058c897 100644 --- a/tests/getversion.c +++ b/tests/core_getversion.c @@ -32,18 +32,17 @@ /** * Checks DRM_IOCTL_GET_VERSION and libdrm's drmGetVersion() interface to it. */ -int main(int argc, char **argv) +igt_simple_main { int fd; drmVersionPtr v; fd = drm_open_any(); v = drmGetVersion(fd); - assert(strlen(v->name) != 0); - assert(strlen(v->date) != 0); - assert(strlen(v->desc) != 0); - assert(v->version_major >= 1); + igt_assert(strlen(v->name) != 0); + igt_assert(strlen(v->date) != 0); + igt_assert(strlen(v->desc) != 0); + igt_assert(v->version_major >= 1); drmFree(v); close(fd); - return 0; } diff --git a/tests/ddi_compute_wrpll.c b/tests/ddi_compute_wrpll.c new file mode 100644 index 00000000..02a96547 --- /dev/null +++ b/tests/ddi_compute_wrpll.c @@ -0,0 +1,634 @@ +#include <stdio.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> + +#include "intel_io.h" +#include "drmtest.h" + +#define LC_FREQ 2700 +#define LC_FREQ_2K (LC_FREQ * 2000) + +#define P_MIN 2 +#define P_MAX 64 +#define P_INC 2 + +/* Constraints for PLL good behavior */ +#define REF_MIN 48 +#define REF_MAX 400 +#define VCO_MIN 2400 +#define VCO_MAX 4800 + +#define ABS_DIFF(a, b) ((a > b) ? (a - b) : (b - a)) + +struct wrpll_rnp { + unsigned p, n2, r2; +}; + +static unsigned wrpll_get_budget_for_freq(int clock) +{ + unsigned budget; + + switch (clock) { + case 25175000: + case 25200000: + case 27000000: + case 27027000: + case 37762500: + case 37800000: + case 40500000: + case 40541000: + case 54000000: + case 54054000: + case 59341000: + case 59400000: + case 72000000: + case 74176000: + case 74250000: + case 81000000: + case 81081000: + case 89012000: + case 89100000: + case 108000000: + case 108108000: + case 111264000: + case 111375000: + case 148352000: + case 148500000: + case 162000000: + case 162162000: + case 222525000: + case 222750000: + case 296703000: + case 297000000: + budget = 0; + break; + case 233500000: + case 245250000: + case 247750000: + case 253250000: + case 298000000: + budget = 1500; + break; + case 169128000: + case 169500000: + case 179500000: + case 202000000: + budget = 2000; + break; + case 256250000: + case 262500000: + case 270000000: + case 272500000: + case 273750000: + case 280750000: + case 281250000: + case 286000000: + case 291750000: + budget = 4000; + break; + case 267250000: + case 268500000: + budget = 5000; + break; + default: + budget = 1000; + break; + } + + return budget; +} + +static void wrpll_update_rnp(uint64_t freq2k, unsigned budget, + unsigned r2, unsigned n2, unsigned p, + struct wrpll_rnp *best) +{ + uint64_t a, b, c, d, diff, diff_best; + + /* No best (r,n,p) yet */ + if (best->p == 0) { + best->p = p; + best->n2 = n2; + best->r2 = r2; + return; + } + + /* + * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to + * freq2k. + * + * delta = 1e6 * + * abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) / + * freq2k; + * + * and we would like delta <= budget. + * + * If the discrepancy is above the PPM-based budget, always prefer to + * improve upon the previous solution. However, if you're within the + * budget, try to maximize Ref * VCO, that is N / (P * R^2). + */ + a = freq2k * budget * p * r2; + b = freq2k * budget * best->p * best->r2; + diff = ABS_DIFF((freq2k * p * r2), (LC_FREQ_2K * n2)); + diff_best = ABS_DIFF((freq2k * best->p * best->r2), + (LC_FREQ_2K * best->n2)); + c = 1000000 * diff; + d = 1000000 * diff_best; + + if (a < c && b < d) { + /* If both are above the budget, pick the closer */ + if (best->p * best->r2 * diff < p * r2 * diff_best) { + best->p = p; + best->n2 = n2; + best->r2 = r2; + } + } else if (a >= c && b < d) { + /* If A is below the threshold but B is above it? Update. */ + best->p = p; + best->n2 = n2; + best->r2 = r2; + } else if (a >= c && b >= d) { + /* Both are below the limit, so pick the higher n2/(r2*r2) */ + if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) { + best->p = p; + best->n2 = n2; + best->r2 = r2; + } + } + /* Otherwise a < c && b >= d, do nothing */ +} + +static void +wrpll_compute_rnp(int clock /* in Hz */, + unsigned *r2_out, unsigned *n2_out, unsigned *p_out) +{ + uint64_t freq2k; + unsigned p, n2, r2; + struct wrpll_rnp best = { 0, 0, 0 }; + unsigned budget; + + freq2k = clock / 100; + + budget = wrpll_get_budget_for_freq(clock); + + /* Special case handling for 540 pixel clock: bypass WR PLL entirely + * and directly pass the LC PLL to it. */ + if (freq2k == 5400000) { + *n2_out = 2; + *p_out = 1; + *r2_out = 2; + return; + } + + /* + * Ref = LC_FREQ / R, where Ref is the actual reference input seen by + * the WR PLL. + * + * We want R so that REF_MIN <= Ref <= REF_MAX. + * Injecting R2 = 2 * R gives: + * REF_MAX * r2 > LC_FREQ * 2 and + * REF_MIN * r2 < LC_FREQ * 2 + * + * Which means the desired boundaries for r2 are: + * LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN + * + */ + for (r2 = LC_FREQ * 2 / REF_MAX + 1; + r2 <= LC_FREQ * 2 / REF_MIN; + r2++) { + + /* + * VCO = N * Ref, that is: VCO = N * LC_FREQ / R + * + * Once again we want VCO_MIN <= VCO <= VCO_MAX. + * Injecting R2 = 2 * R and N2 = 2 * N, we get: + * VCO_MAX * r2 > n2 * LC_FREQ and + * VCO_MIN * r2 < n2 * LC_FREQ) + * + * Which means the desired boundaries for n2 are: + * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ + */ + for (n2 = VCO_MIN * r2 / LC_FREQ + 1; + n2 <= VCO_MAX * r2 / LC_FREQ; + n2++) { + + for (p = P_MIN; p <= P_MAX; p += P_INC) + wrpll_update_rnp(freq2k, budget, + r2, n2, p, &best); + } + } + + *n2_out = best.n2; + *p_out = best.p; + *r2_out = best.r2; +} + +/* WRPLL clock dividers */ +struct wrpll_tmds_clock { + uint32_t clock; + uint16_t p; /* Post divider */ + uint16_t n2; /* Feedback divider */ + uint16_t r2; /* Reference divider */ +}; + +/* Table of matching values for WRPLL clocks programming for each frequency. + * The code assumes this table is sorted. */ +static const struct wrpll_tmds_clock wrpll_tmds_clock_table[] = { + {19750000, 38, 25, 18}, + {20000000, 48, 32, 18}, + {21000000, 36, 21, 15}, + {21912000, 42, 29, 17}, + {22000000, 36, 22, 15}, + {23000000, 36, 23, 15}, + {23500000, 40, 40, 23}, + {23750000, 26, 16, 14}, + {24000000, 36, 24, 15}, + {25000000, 36, 25, 15}, + {25175000, 26, 40, 33}, + {25200000, 30, 21, 15}, + {26000000, 36, 26, 15}, + {27000000, 30, 21, 14}, + {27027000, 18, 100, 111}, + {27500000, 30, 29, 19}, + {28000000, 34, 30, 17}, + {28320000, 26, 30, 22}, + {28322000, 32, 42, 25}, + {28750000, 24, 23, 18}, + {29000000, 30, 29, 18}, + {29750000, 32, 30, 17}, + {30000000, 30, 25, 15}, + {30750000, 30, 41, 24}, + {31000000, 30, 31, 18}, + {31500000, 30, 28, 16}, + {32000000, 30, 32, 18}, + {32500000, 28, 32, 19}, + {33000000, 24, 22, 15}, + {34000000, 28, 30, 17}, + {35000000, 26, 32, 19}, + {35500000, 24, 30, 19}, + {36000000, 26, 26, 15}, + {36750000, 26, 46, 26}, + {37000000, 24, 23, 14}, + {37762500, 22, 40, 26}, + {37800000, 20, 21, 15}, + {38000000, 24, 27, 16}, + {38250000, 24, 34, 20}, + {39000000, 24, 26, 15}, + {40000000, 24, 32, 18}, + {40500000, 20, 21, 14}, + {40541000, 22, 147, 89}, + {40750000, 18, 19, 14}, + {41000000, 16, 17, 14}, + {41500000, 22, 44, 26}, + {41540000, 22, 44, 26}, + {42000000, 18, 21, 15}, + {42500000, 22, 45, 26}, + {43000000, 20, 43, 27}, + {43163000, 20, 24, 15}, + {44000000, 18, 22, 15}, + {44900000, 20, 108, 65}, + {45000000, 20, 25, 15}, + {45250000, 20, 52, 31}, + {46000000, 18, 23, 15}, + {46750000, 20, 45, 26}, + {47000000, 20, 40, 23}, + {48000000, 18, 24, 15}, + {49000000, 18, 49, 30}, + {49500000, 16, 22, 15}, + {50000000, 18, 25, 15}, + {50500000, 18, 32, 19}, + {51000000, 18, 34, 20}, + {52000000, 18, 26, 15}, + {52406000, 14, 34, 25}, + {53000000, 16, 22, 14}, + {54000000, 16, 24, 15}, + {54054000, 16, 173, 108}, + {54500000, 14, 24, 17}, + {55000000, 12, 22, 18}, + {56000000, 14, 45, 31}, + {56250000, 16, 25, 15}, + {56750000, 14, 25, 17}, + {57000000, 16, 27, 16}, + {58000000, 16, 43, 25}, + {58250000, 16, 38, 22}, + {58750000, 16, 40, 23}, + {59000000, 14, 26, 17}, + {59341000, 14, 40, 26}, + {59400000, 16, 44, 25}, + {60000000, 16, 32, 18}, + {60500000, 12, 39, 29}, + {61000000, 14, 49, 31}, + {62000000, 14, 37, 23}, + {62250000, 14, 42, 26}, + {63000000, 12, 21, 15}, + {63500000, 14, 28, 17}, + {64000000, 12, 27, 19}, + {65000000, 14, 32, 19}, + {65250000, 12, 29, 20}, + {65500000, 12, 32, 22}, + {66000000, 12, 22, 15}, + {66667000, 14, 38, 22}, + {66750000, 10, 21, 17}, + {67000000, 14, 33, 19}, + {67750000, 14, 58, 33}, + {68000000, 14, 30, 17}, + {68179000, 14, 46, 26}, + {68250000, 14, 46, 26}, + {69000000, 12, 23, 15}, + {70000000, 12, 28, 18}, + {71000000, 12, 30, 19}, + {72000000, 12, 24, 15}, + {73000000, 10, 23, 17}, + {74000000, 12, 23, 14}, + {74176000, 8, 100, 91}, + {74250000, 10, 22, 16}, + {74481000, 12, 43, 26}, + {74500000, 10, 29, 21}, + {75000000, 12, 25, 15}, + {75250000, 10, 39, 28}, + {76000000, 12, 27, 16}, + {77000000, 12, 53, 31}, + {78000000, 12, 26, 15}, + {78750000, 12, 28, 16}, + {79000000, 10, 38, 26}, + {79500000, 10, 28, 19}, + {80000000, 12, 32, 18}, + {81000000, 10, 21, 14}, + {81081000, 6, 100, 111}, + {81624000, 8, 29, 24}, + {82000000, 8, 17, 14}, + {83000000, 10, 40, 26}, + {83950000, 10, 28, 18}, + {84000000, 10, 28, 18}, + {84750000, 6, 16, 17}, + {85000000, 6, 17, 18}, + {85250000, 10, 30, 19}, + {85750000, 10, 27, 17}, + {86000000, 10, 43, 27}, + {87000000, 10, 29, 18}, + {88000000, 10, 44, 27}, + {88500000, 10, 41, 25}, + {89000000, 10, 28, 17}, + {89012000, 6, 90, 91}, + {89100000, 10, 33, 20}, + {90000000, 10, 25, 15}, + {91000000, 10, 32, 19}, + {92000000, 10, 46, 27}, + {93000000, 10, 31, 18}, + {94000000, 10, 40, 23}, + {94500000, 10, 28, 16}, + {95000000, 10, 44, 25}, + {95654000, 10, 39, 22}, + {95750000, 10, 39, 22}, + {96000000, 10, 32, 18}, + {97000000, 8, 23, 16}, + {97750000, 8, 42, 29}, + {98000000, 8, 45, 31}, + {99000000, 8, 22, 15}, + {99750000, 8, 34, 23}, + {100000000, 6, 20, 18}, + {100500000, 6, 19, 17}, + {101000000, 6, 37, 33}, + {101250000, 8, 21, 14}, + {102000000, 6, 17, 15}, + {102250000, 6, 25, 22}, + {103000000, 8, 29, 19}, + {104000000, 8, 37, 24}, + {105000000, 8, 28, 18}, + {106000000, 8, 22, 14}, + {107000000, 8, 46, 29}, + {107214000, 8, 27, 17}, + {108000000, 8, 24, 15}, + {108108000, 8, 173, 108}, + {109000000, 6, 23, 19}, + {110000000, 6, 22, 18}, + {110013000, 6, 22, 18}, + {110250000, 8, 49, 30}, + {110500000, 8, 36, 22}, + {111000000, 8, 23, 14}, + {111264000, 8, 150, 91}, + {111375000, 8, 33, 20}, + {112000000, 8, 63, 38}, + {112500000, 8, 25, 15}, + {113100000, 8, 57, 34}, + {113309000, 8, 42, 25}, + {114000000, 8, 27, 16}, + {115000000, 6, 23, 18}, + {116000000, 8, 43, 25}, + {117000000, 8, 26, 15}, + {117500000, 8, 40, 23}, + {118000000, 6, 38, 29}, + {119000000, 8, 30, 17}, + {119500000, 8, 46, 26}, + {119651000, 8, 39, 22}, + {120000000, 8, 32, 18}, + {121000000, 6, 39, 29}, + {121250000, 6, 31, 23}, + {121750000, 6, 23, 17}, + {122000000, 6, 42, 31}, + {122614000, 6, 30, 22}, + {123000000, 6, 41, 30}, + {123379000, 6, 37, 27}, + {124000000, 6, 51, 37}, + {125000000, 6, 25, 18}, + {125250000, 4, 13, 14}, + {125750000, 4, 27, 29}, + {126000000, 6, 21, 15}, + {127000000, 6, 24, 17}, + {127250000, 6, 41, 29}, + {128000000, 6, 27, 19}, + {129000000, 6, 43, 30}, + {129859000, 4, 25, 26}, + {130000000, 6, 26, 18}, + {130250000, 6, 42, 29}, + {131000000, 6, 32, 22}, + {131500000, 6, 38, 26}, + {131850000, 6, 41, 28}, + {132000000, 6, 22, 15}, + {132750000, 6, 28, 19}, + {133000000, 6, 34, 23}, + {133330000, 6, 37, 25}, + {134000000, 6, 61, 41}, + {135000000, 6, 21, 14}, + {135250000, 6, 167, 111}, + {136000000, 6, 62, 41}, + {137000000, 6, 35, 23}, + {138000000, 6, 23, 15}, + {138500000, 6, 40, 26}, + {138750000, 6, 37, 24}, + {139000000, 6, 34, 22}, + {139050000, 6, 34, 22}, + {139054000, 6, 34, 22}, + {140000000, 6, 28, 18}, + {141000000, 6, 36, 23}, + {141500000, 6, 22, 14}, + {142000000, 6, 30, 19}, + {143000000, 6, 27, 17}, + {143472000, 4, 17, 16}, + {144000000, 6, 24, 15}, + {145000000, 6, 29, 18}, + {146000000, 6, 47, 29}, + {146250000, 6, 26, 16}, + {147000000, 6, 49, 30}, + {147891000, 6, 23, 14}, + {148000000, 6, 23, 14}, + {148250000, 6, 28, 17}, + {148352000, 4, 100, 91}, + {148500000, 6, 33, 20}, + {149000000, 6, 48, 29}, + {150000000, 6, 25, 15}, + {151000000, 4, 19, 17}, + {152000000, 6, 27, 16}, + {152280000, 6, 44, 26}, + {153000000, 6, 34, 20}, + {154000000, 6, 53, 31}, + {155000000, 6, 31, 18}, + {155250000, 6, 50, 29}, + {155750000, 6, 45, 26}, + {156000000, 6, 26, 15}, + {157000000, 6, 61, 35}, + {157500000, 6, 28, 16}, + {158000000, 6, 65, 37}, + {158250000, 6, 44, 25}, + {159000000, 6, 53, 30}, + {159500000, 6, 39, 22}, + {160000000, 6, 32, 18}, + {161000000, 4, 31, 26}, + {162000000, 4, 18, 15}, + {162162000, 4, 131, 109}, + {162500000, 4, 53, 44}, + {163000000, 4, 29, 24}, + {164000000, 4, 17, 14}, + {165000000, 4, 22, 18}, + {166000000, 4, 32, 26}, + {167000000, 4, 26, 21}, + {168000000, 4, 46, 37}, + {169000000, 4, 104, 83}, + {169128000, 4, 64, 51}, + {169500000, 4, 39, 31}, + {170000000, 4, 34, 27}, + {171000000, 4, 19, 15}, + {172000000, 4, 51, 40}, + {172750000, 4, 32, 25}, + {172800000, 4, 32, 25}, + {173000000, 4, 41, 32}, + {174000000, 4, 49, 38}, + {174787000, 4, 22, 17}, + {175000000, 4, 35, 27}, + {176000000, 4, 30, 23}, + {177000000, 4, 38, 29}, + {178000000, 4, 29, 22}, + {178500000, 4, 37, 28}, + {179000000, 4, 53, 40}, + {179500000, 4, 73, 55}, + {180000000, 4, 20, 15}, + {181000000, 4, 55, 41}, + {182000000, 4, 31, 23}, + {183000000, 4, 42, 31}, + {184000000, 4, 30, 22}, + {184750000, 4, 26, 19}, + {185000000, 4, 37, 27}, + {186000000, 4, 51, 37}, + {187000000, 4, 36, 26}, + {188000000, 4, 32, 23}, + {189000000, 4, 21, 15}, + {190000000, 4, 38, 27}, + {190960000, 4, 41, 29}, + {191000000, 4, 41, 29}, + {192000000, 4, 27, 19}, + {192250000, 4, 37, 26}, + {193000000, 4, 20, 14}, + {193250000, 4, 53, 37}, + {194000000, 4, 23, 16}, + {194208000, 4, 23, 16}, + {195000000, 4, 26, 18}, + {196000000, 4, 45, 31}, + {197000000, 4, 35, 24}, + {197750000, 4, 41, 28}, + {198000000, 4, 22, 15}, + {198500000, 4, 25, 17}, + {199000000, 4, 28, 19}, + {200000000, 4, 37, 25}, + {201000000, 4, 61, 41}, + {202000000, 4, 112, 75}, + {202500000, 4, 21, 14}, + {203000000, 4, 146, 97}, + {204000000, 4, 62, 41}, + {204750000, 4, 44, 29}, + {205000000, 4, 38, 25}, + {206000000, 4, 29, 19}, + {207000000, 4, 23, 15}, + {207500000, 4, 40, 26}, + {208000000, 4, 37, 24}, + {208900000, 4, 48, 31}, + {209000000, 4, 48, 31}, + {209250000, 4, 31, 20}, + {210000000, 4, 28, 18}, + {211000000, 4, 25, 16}, + {212000000, 4, 22, 14}, + {213000000, 4, 30, 19}, + {213750000, 4, 38, 24}, + {214000000, 4, 46, 29}, + {214750000, 4, 35, 22}, + {215000000, 4, 43, 27}, + {216000000, 4, 24, 15}, + {217000000, 4, 37, 23}, + {218000000, 4, 42, 26}, + {218250000, 4, 42, 26}, + {218750000, 4, 34, 21}, + {219000000, 4, 47, 29}, + {220000000, 4, 44, 27}, + {220640000, 4, 49, 30}, + {220750000, 4, 36, 22}, + {221000000, 4, 36, 22}, + {222000000, 4, 23, 14}, + {222525000, 4, 150, 91}, + {222750000, 4, 33, 20}, + {227000000, 4, 37, 22}, + {230250000, 4, 29, 17}, + {233500000, 4, 38, 22}, + {235000000, 4, 40, 23}, + {238000000, 4, 30, 17}, + {241500000, 2, 17, 19}, + {245250000, 2, 20, 22}, + {247750000, 2, 22, 24}, + {253250000, 2, 15, 16}, + {256250000, 2, 18, 19}, + {262500000, 2, 31, 32}, + {267250000, 2, 66, 67}, + {268500000, 2, 94, 95}, + {270000000, 2, 14, 14}, + {272500000, 2, 77, 76}, + {273750000, 2, 57, 56}, + {280750000, 2, 24, 23}, + {281250000, 2, 23, 22}, + {286000000, 2, 17, 16}, + {291750000, 2, 26, 24}, + {296703000, 2, 100, 91}, + {297000000, 2, 22, 20}, + {298000000, 2, 21, 19}, +}; + +int main(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(wrpll_tmds_clock_table); i++) { + const struct wrpll_tmds_clock *ref = &wrpll_tmds_clock_table[i]; + unsigned r2, n2, p; + + wrpll_compute_rnp(ref->clock, &r2, &n2, &p); + if (ref->r2 != r2 || ref->n2 != n2 || ref->p != p) { + printf("Computed value differs for %li Hz:\n" + " Reference: (%u,%u,%u)\n" + " Computed: (%u,%u,%u)\n", + (int64_t)ref->clock * 1000, + ref->r2, ref->n2, ref->p, + r2, n2, p); + + abort(); + } + } + + return 0; +} diff --git a/tests/ddx_intel_after_fbdev b/tests/ddx_intel_after_fbdev new file mode 100755 index 00000000..bcd2c29d --- /dev/null +++ b/tests/ddx_intel_after_fbdev @@ -0,0 +1,73 @@ +#!/bin/bash +# +# Testcase: Load Intel DDX after fbdev was loaded +# + +whoami | grep -q root || { + echo "ERROR: not running as root" + exit 1 +} + +# no other X session should be running +find /tmp/ -name .X*lock 2>/dev/null | grep -q X && { + echo "ERROR: X session already running" + exit 1 +} + +TMPDIR=$(mktemp -d /tmp/igt.XXXX) || { + echo "ERROR: Failed to create temp dir" + exit 1 +} + +cat > $TMPDIR/xorg.conf.fbdev << EOF +Section "Device" + Driver "fbdev" + Identifier "Device[fbdev]" +EndSection +EOF + +cat > $TMPDIR/xorg.conf.intel << EOF +Section "Device" + Driver "intel" + Identifier "Device[intel]" +EndSection +EOF + +# log before fbdev +dmesg -c > $TMPDIR/dmesg.1.before.fbdev +cp /var/log/Xorg.0.log $TMPDIR/Xorg.0.log.1.before.fbdev + +# run fbdev +xinit -- /usr/bin/X -config $TMPDIR/xorg.conf.fbdev & +sleep 5 +if [ -f `which intel_reg_dumper` ]; then +`which intel_reg_dumper` > $TMPDIR/intel_reg_dumped.1.fbdev +fi +killall X + +# log after fbdev & before intel +dmesg -c > $TMPDIR/dmesg.2.after.fbdev.before.intel +cp /var/log/Xorg.0.log $TMPDIR/Xorg.0.log.2.after.fbdev.before.intel + +sleep 5 + +# run intel +xinit -- /usr/bin/X -config $TMPDIR/xorg.conf.intel & +sleep 5 +if [ -f `which intel_reg_dumper` ]; then +`which intel_reg_dumper` > $TMPDIR/intel_reg_dumped.2.intel +fi +killall X + +# log after intel +dmesg -c > $TMPDIR/dmesg.3.after.intel +cp /var/log/Xorg.0.log $TMPDIR/Xorg.0.log.3.after.intel + +cp $0 $TMPDIR/ + +tar czf $TMPDIR.tar.gz $TMPDIR/* +if [ -f $TMPDIR.tar.gz ]; then + echo $TMPDIR.tar.gz contains this script, all configs and logs generated on this tests +fi + +exit 0 diff --git a/tests/debugfs_emon_crash b/tests/debugfs_emon_crash index 6e139a41..809bfab3 100755 --- a/tests/debugfs_emon_crash +++ b/tests/debugfs_emon_crash @@ -8,7 +8,7 @@ SOURCE_DIR="$( dirname "${BASH_SOURCE[0]}" )" . $SOURCE_DIR/drm_lib.sh for z in $(seq 1 1000); do - cat $i915_path/i915_emon_status > /dev/null 2&>1 + cat $i915_dfs_path/i915_emon_status > /dev/null 2&>1 done # If we got here, we haven't crashed diff --git a/tests/debugfs_wedged b/tests/debugfs_wedged index 80a32f61..903a0a20 100755 --- a/tests/debugfs_wedged +++ b/tests/debugfs_wedged @@ -6,5 +6,5 @@ SOURCE_DIR="$( dirname "${BASH_SOURCE[0]}" )" # Testcase: wedge the hw to check the error_state reading # # Unfortunately wedged is permanent, so this test is not run by default -echo 1 > ${i915_path}/i915_wedged -cat $i915_path/i915_error_state > /dev/null 2>&1 +echo 1 > ${i915_dfs_path}/i915_wedged +cat $i915_dfs_path/i915_error_state > /dev/null 2>&1 diff --git a/tests/drm_lib.sh b/tests/drm_lib.sh index a76fd474..97f6f925 100755 --- a/tests/drm_lib.sh +++ b/tests/drm_lib.sh @@ -4,6 +4,10 @@ die() { exit 1 } +do_or_die() { + $@ > /dev/null 2>&1 || (echo "FAIL: $@ ($?)" && exit -1) +} + if [ -d /debug/dri ] ; then debugfs_path=/debug/dri fi @@ -12,21 +16,36 @@ if [ -d /sys/kernel/debug/dri ] ; then debugfs_path=/sys/kernel/debug/dri fi -i915_path=x -for dir in `ls $debugfs_path` ; do - if [ -f $debugfs_path/$dir/i915_error_state ] ; then - i915_path=$debugfs_path/$dir +i915_dfs_path=x +for minor in `seq 0 16`; do + if [ -f $debugfs_path/$minor/i915_error_state ] ; then + i915_dfs_path=$debugfs_path/$minor break fi done -if [ $i915_path = "x" ] ; then +if [ $i915_dfs_path = "x" ] ; then die " i915 debugfs path not found." fi # read everything we can -if [ `cat $i915_path/clients | wc -l` -gt "2" ] ; then - die "ERROR: other drm clients running" +if [ `cat $i915_dfs_path/clients | wc -l` -gt "2" ] ; then + [ -n "$DRM_LIB_ALLOW_NO_MASTER" ] || \ + die "ERROR: other drm clients running" fi +i915_sfs_path= +if [ -d /sys/class/drm ] ; then + sysfs_path=/sys/class/drm + if [ -f $sysfs_path/card$minor/error ] ; then + i915_sfs_path="$sysfs_path/card$minor" + fi +fi +# sysfs may not exist as the 'error' is a new interface in 3.11 + +function drmtest_skip_on_simulation() +{ + [ -n "$INTEL_SIMULATION" ] && exit 77 +} +drmtest_skip_on_simulation diff --git a/tests/drm_vma_limiter.c b/tests/drm_vma_limiter.c index 1971e2dc..e1381fe3 100644 --- a/tests/drm_vma_limiter.c +++ b/tests/drm_vma_limiter.c @@ -27,18 +27,18 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "intel_chipset.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; @@ -54,12 +54,14 @@ struct intel_batchbuffer *batch; #define BO_ARRAY_SIZE 35000 drm_intel_bo *bos[BO_ARRAY_SIZE]; -int main(int argc, char **argv) +igt_simple_main { int fd; int i; char *ptr; + igt_skip_on_simulation(); + fd = drm_open_any(); bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); @@ -70,17 +72,17 @@ int main(int argc, char **argv) for (i = 0; i < BO_ARRAY_SIZE; i++) { bos[i] = drm_intel_bo_alloc(bufmgr, "mmap bo", 4096, 4096); - assert(bos[i]); + igt_assert(bos[i]); drm_intel_bo_map(bos[i], 1); ptr = bos[i]->virtual; - assert(ptr); + igt_assert(ptr); *ptr = 'c'; drm_intel_bo_unmap(bos[i]); drm_intel_gem_bo_map_gtt(bos[i]); ptr = bos[i]->virtual; - assert(ptr); + igt_assert(ptr); *ptr = 'c'; drm_intel_gem_bo_unmap_gtt(bos[i]); } @@ -88,16 +90,16 @@ int main(int argc, char **argv) /* and recheck whether a second map of the same still works */ for (i = 0; i < BO_ARRAY_SIZE; i++) { bos[i] = drm_intel_bo_alloc(bufmgr, "mmap bo", 4096, 4096); - assert(bos[i]); + igt_assert(bos[i]); drm_intel_bo_map(bos[i], 1); ptr = bos[i]->virtual; - assert(*ptr = 'c'); + igt_assert(*ptr = 'c'); drm_intel_bo_unmap(bos[i]); drm_intel_gem_bo_map_gtt(bos[i]); ptr = bos[i]->virtual; - assert(*ptr = 'c'); + igt_assert(*ptr = 'c'); drm_intel_gem_bo_unmap_gtt(bos[i]); } @@ -105,6 +107,4 @@ int main(int argc, char **argv) drm_intel_bufmgr_destroy(bufmgr); close(fd); - - return 0; } diff --git a/tests/drm_vma_limiter_cached.c b/tests/drm_vma_limiter_cached.c index 37976185..3b41caad 100644 --- a/tests/drm_vma_limiter_cached.c +++ b/tests/drm_vma_limiter_cached.c @@ -27,18 +27,18 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "intel_chipset.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; @@ -54,13 +54,15 @@ struct intel_batchbuffer *batch; /* we do both cpu and gtt maps, so only need half of 64k to exhaust */ -int main(int argc, char **argv) +igt_simple_main { int fd; int i; char *ptr; drm_intel_bo *load_bo; + igt_skip_on_simulation(); + fd = drm_open_any(); bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); @@ -68,7 +70,7 @@ int main(int argc, char **argv) batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); load_bo = drm_intel_bo_alloc(bufmgr, "target bo", 1024*4096, 4096); - assert(load_bo); + igt_assert(load_bo); drm_intel_bufmgr_gem_set_vma_cache_size(bufmgr, 500); @@ -79,19 +81,18 @@ int main(int argc, char **argv) /* put some load onto the gpu to keep the light buffers active for long * enough */ for (i = 0; i < 10000; i++) { - BEGIN_BATCH(8); - OUT_BATCH(XY_SRC_COPY_BLT_CMD | - XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); + BLIT_COPY_BATCH_START(batch->devid, 0); OUT_BATCH((3 << 24) | /* 32 bits */ (0xcc << 16) | /* copy ROP */ 4096); OUT_BATCH(0); /* dst x1,y1 */ OUT_BATCH((1024 << 16) | 512); OUT_RELOC(load_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(batch->devid); OUT_BATCH((0 << 16) | 512); /* src x1, y1 */ OUT_BATCH(4096); OUT_RELOC(load_bo, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(batch->devid); ADVANCE_BATCH(); } @@ -102,24 +103,22 @@ int main(int argc, char **argv) for (j = 0; j < GROUP_SZ; j++, i++) { bo[j] = drm_intel_bo_alloc(bufmgr, "mmap bo", 4096, 4096); - assert(bo[j]); + igt_assert(bo[j]); drm_intel_gem_bo_map_gtt(bo[j]); ptr = bo[j]->virtual; - assert(ptr); + igt_assert(ptr); *ptr = 'c'; drm_intel_gem_bo_unmap_gtt(bo[j]); /* put it onto the active list ... */ - BEGIN_BATCH(6); - OUT_BATCH(XY_COLOR_BLT_CMD | - XY_COLOR_BLT_WRITE_ALPHA | - XY_COLOR_BLT_WRITE_RGB); + COLOR_BLIT_COPY_BATCH_START(intel_get_drm_devid(fd), 0); OUT_BATCH((3 << 24) | /* 32 bits */ 128); OUT_BATCH(0); /* dst x1,y1 */ OUT_BATCH((1 << 16) | 1); OUT_RELOC(bo[j], I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(intel_get_drm_devid(fd)); OUT_BATCH(0xffffffff); /* color */ ADVANCE_BATCH(); } @@ -133,6 +132,4 @@ int main(int argc, char **argv) drm_intel_bufmgr_destroy(bufmgr); close(fd); - - return 0; } diff --git a/tests/drm_vma_limiter_cpu.c b/tests/drm_vma_limiter_cpu.c index 24ce188e..e17a679d 100644 --- a/tests/drm_vma_limiter_cpu.c +++ b/tests/drm_vma_limiter_cpu.c @@ -27,18 +27,18 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "intel_chipset.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; @@ -55,12 +55,14 @@ struct intel_batchbuffer *batch; #define BO_ARRAY_SIZE 68000 drm_intel_bo *bos[BO_ARRAY_SIZE]; -int main(int argc, char **argv) +igt_simple_main { int fd; int i; char *ptr; + igt_skip_on_simulation(); + fd = drm_open_any(); bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); @@ -71,11 +73,11 @@ int main(int argc, char **argv) for (i = 0; i < BO_ARRAY_SIZE; i++) { bos[i] = drm_intel_bo_alloc(bufmgr, "mmap bo", 4096, 4096); - assert(bos[i]); + igt_assert(bos[i]); drm_intel_bo_map(bos[i], 1); ptr = bos[i]->virtual; - assert(ptr); + igt_assert(ptr); *ptr = 'c'; drm_intel_bo_unmap(bos[i]); } @@ -83,11 +85,11 @@ int main(int argc, char **argv) /* and recheck whether a second map of the same still works */ for (i = 0; i < BO_ARRAY_SIZE; i++) { bos[i] = drm_intel_bo_alloc(bufmgr, "mmap bo", 4096, 4096); - assert(bos[i]); + igt_assert(bos[i]); drm_intel_bo_map(bos[i], 1); ptr = bos[i]->virtual; - assert(*ptr = 'c'); + igt_assert(*ptr = 'c'); drm_intel_bo_unmap(bos[i]); } @@ -95,6 +97,4 @@ int main(int argc, char **argv) drm_intel_bufmgr_destroy(bufmgr); close(fd); - - return 0; } diff --git a/tests/drm_vma_limiter_gtt.c b/tests/drm_vma_limiter_gtt.c index 540ea917..303e86da 100644 --- a/tests/drm_vma_limiter_gtt.c +++ b/tests/drm_vma_limiter_gtt.c @@ -27,18 +27,18 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "intel_chipset.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; @@ -56,12 +56,14 @@ struct intel_batchbuffer *batch; #define BO_ARRAY_SIZE 68000 drm_intel_bo *bos[BO_ARRAY_SIZE]; -int main(int argc, char **argv) +igt_simple_main { int fd; int i; char *ptr; + igt_skip_on_simulation(); + fd = drm_open_any(); bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); @@ -72,11 +74,11 @@ int main(int argc, char **argv) for (i = 0; i < BO_ARRAY_SIZE; i++) { bos[i] = drm_intel_bo_alloc(bufmgr, "mmap bo", 4096, 4096); - assert(bos[i]); + igt_assert(bos[i]); drm_intel_gem_bo_map_gtt(bos[i]); ptr = bos[i]->virtual; - assert(ptr); + igt_assert(ptr); *ptr = 'c'; drm_intel_gem_bo_unmap_gtt(bos[i]); } @@ -84,11 +86,11 @@ int main(int argc, char **argv) /* and recheck whether a second map of the same still works */ for (i = 0; i < BO_ARRAY_SIZE; i++) { bos[i] = drm_intel_bo_alloc(bufmgr, "mmap bo", 4096, 4096); - assert(bos[i]); + igt_assert(bos[i]); drm_intel_gem_bo_map_gtt(bos[i]); ptr = bos[i]->virtual; - assert(*ptr = 'c'); + igt_assert(*ptr = 'c'); drm_intel_gem_bo_unmap_gtt(bos[i]); } @@ -96,6 +98,4 @@ int main(int argc, char **argv) drm_intel_bufmgr_destroy(bufmgr); close(fd); - - return 0; } diff --git a/tests/debugfs_reader b/tests/drv_debugfs_reader index 80d59988..9e2845eb 100755 --- a/tests/debugfs_reader +++ b/tests/drv_debugfs_reader @@ -4,6 +4,6 @@ SOURCE_DIR="$( dirname "${BASH_SOURCE[0]}" )" . $SOURCE_DIR/drm_lib.sh # read everything we can -cat $i915_path/* > /dev/null 2>&1 +cat $i915_dfs_path/* > /dev/null 2>&1 exit 0 diff --git a/tests/drv_hangman.c b/tests/drv_hangman.c new file mode 100644 index 00000000..d74ed483 --- /dev/null +++ b/tests/drv_hangman.c @@ -0,0 +1,428 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Mika Kuoppala <mika.kuoppala@intel.com> + * Oscar Mateo <oscar.mateo@intel.com> + * + */ + +#include <limits.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include "intel_chipset.h" +#include "drmtest.h" +#include "igt_debugfs.h" +#include "ioctl_wrappers.h" + +static int _read_sysfs(void *dst, int maxlen, + const char* path, + const char *fname) +{ + int fd; + char full[PATH_MAX]; + int r, e; + + igt_assert(snprintf(full, PATH_MAX, "%s/%s", path, fname) < PATH_MAX); + + fd = open(full, O_RDONLY); + if (fd == -1) + return -errno; + + r = read(fd, dst, maxlen); + e = errno; + close(fd); + + if (r < 0) + return -e; + + return r; +} + +static int read_sysfs(void *dst, int maxlen, const char *fname) +{ + char path[PATH_MAX]; + + igt_assert(snprintf(path, PATH_MAX, "/sys/class/drm/card%d", + drm_get_card()) < PATH_MAX); + + return _read_sysfs(dst, maxlen, path, fname); +} + +static void test_sysfs_error_exists(void) +{ + char tmp[1024]; + + igt_assert(read_sysfs(tmp, sizeof(tmp), "error") > 0); +} + +static void test_debugfs_error_state_exists(void) +{ + int fd; + + igt_assert((fd = igt_debugfs_open("i915_error_state", O_RDONLY)) >= 0); + + close (fd); +} + +static void test_debugfs_ring_stop_exists(void) +{ + int fd; + + igt_assert((fd = igt_debugfs_open("i915_ring_stop", O_RDONLY)) >= 0); + + close(fd); +} + +static void read_dfs(const char *fname, char *d, int maxlen) +{ + int fd; + int l; + + igt_assert((fd = igt_debugfs_open(fname, O_RDONLY)) >= 0); + + igt_assert((l = read(fd, d, maxlen-1)) > 0); + igt_assert(l < maxlen); + d[l] = 0; + close(fd); + + igt_debug("dfs entry %s read '%s'\n", fname, d); +} + +static void _assert_dfs_entry(const char *fname, const char *s, bool inverse) +{ + char tmp[1024]; + const int l = strlen(s) < sizeof(tmp) ? + strlen(s) : sizeof(tmp); + + read_dfs(fname, tmp, l + 1); + if (!inverse) { + if (strncmp(tmp, s, l) != 0) { + fprintf(stderr, "contents of %s: '%s' (expected '%s')\n", + fname, tmp, s); + igt_fail(1); + } + } else { + if (strncmp(tmp, s, l) == 0) { + fprintf(stderr, "contents of %s: '%s' (expected not '%s'\n", + fname, tmp, s); + igt_fail(1); + } + } +} + +static void assert_dfs_entry(const char *fname, const char *s) +{ + _assert_dfs_entry(fname, s, false); +} + +static void assert_dfs_entry_not(const char *fname, const char *s) +{ + _assert_dfs_entry(fname, s, true); +} + +static void assert_error_state_clear(void) +{ + assert_dfs_entry("i915_error_state", "no error state collected"); +} + +static void assert_error_state_collected(void) +{ + assert_dfs_entry_not("i915_error_state", "no error state collected"); +} + +static int get_line_count(const char *s) +{ + int count = 0; + + while (*s) { + if (*s == '\n') + count++; + s++; + } + + return count; +} + +static void check_other_clients(void) +{ + char tmp[1024]; + char *s; + int dev, pid, uid, magic; + + read_dfs("clients", tmp, sizeof(tmp)); + if (get_line_count(tmp) <= 2) + return; + + s = strstr(tmp, "y"); + igt_assert(s != NULL); + igt_assert(sscanf(s, "y %d %d %d %d", + &dev, &pid, &uid, &magic) == 4); + + igt_debug("client %d %d %d %d\n", dev, pid, uid, magic); + igt_assert(pid == getpid()); + igt_debug("found myself in client list\n"); +} + +#define MAGIC_NUMBER 0x10001 +const uint32_t batch[] = { MI_NOOP, + MI_BATCH_BUFFER_END, + MAGIC_NUMBER, + MAGIC_NUMBER }; + +static uint64_t submit_batch(int fd, unsigned ring_id, bool stop_ring) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 exec; + uint64_t presumed_offset; + + gem_require_ring(fd, ring_id); + + exec.handle = gem_create(fd, 4096); + gem_write(fd, exec.handle, 0, batch, sizeof(batch)); + exec.relocation_count = 0; + exec.relocs_ptr = 0; + exec.alignment = 0; + exec.offset = 0; + exec.flags = 0; + exec.rsvd1 = 0; + exec.rsvd2 = 0; + + execbuf.buffers_ptr = (uintptr_t)&exec; + execbuf.buffer_count = 1; + execbuf.batch_start_offset = 0; + execbuf.batch_len = sizeof(batch); + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = ring_id; + i915_execbuffer2_set_context_id(execbuf, 0); + execbuf.rsvd2 = 0; + + gem_execbuf(fd, &execbuf); + gem_sync(fd, exec.handle); + presumed_offset = exec.offset; + + if (stop_ring) { + igt_set_stop_rings(igt_to_stop_ring_flag(ring_id)); + + gem_execbuf(fd, &execbuf); + gem_sync(fd, exec.handle); + + igt_assert(igt_get_stop_rings() == STOP_RING_NONE); + igt_assert(presumed_offset == exec.offset); + } + + gem_close(fd, exec.handle); + + return exec.offset; +} + +static void clear_error_state(void) +{ + int fd; + const char *b = "1"; + + igt_assert((fd = igt_debugfs_open("i915_error_state", O_WRONLY)) >= 0); + igt_assert(write(fd, b, 1) == 1); + close(fd); +} + +static void test_error_state_basic(void) +{ + int fd; + + check_other_clients(); + clear_error_state(); + assert_error_state_clear(); + + fd = drm_open_any(); + submit_batch(fd, I915_EXEC_RENDER, true); + close(fd); + + assert_error_state_collected(); + clear_error_state(); + assert_error_state_clear(); +} + +static void check_error_state(const int gen, + const char *expected_ring_name, + uint64_t expected_offset) +{ + FILE *file; + int debug_fd; + char *line = NULL; + size_t line_size = 0; + char *ring_name = NULL; + bool bb_ok = false, req_ok = false, ringbuf_ok = false; + + debug_fd = igt_debugfs_open("i915_error_state", O_RDONLY); + igt_assert(debug_fd >= 0); + file = fdopen(debug_fd, "r"); + + while (getline(&line, &line_size, file) > 0) { + char *dashes = NULL; + int bb_matched = 0; + uint32_t gtt_offset; + int req_matched = 0; + int requests; + uint32_t tail; + int ringbuf_matched = 0; + int i, items; + + dashes = strstr(line, "---"); + if (!dashes) + continue; + + ring_name = realloc(ring_name, dashes - line); + strncpy(ring_name, line, dashes - line); + ring_name[dashes - line - 1] = '\0'; + + bb_matched = sscanf(dashes, "--- gtt_offset = 0x%08x\n", + >t_offset); + if (bb_matched == 1) { + char expected_line[32]; + + igt_assert(strstr(ring_name, expected_ring_name)); + igt_assert(gtt_offset == expected_offset); + + for (i = 0; i < sizeof(batch) / 4; i++) { + igt_assert(getline(&line, &line_size, file) > 0); + snprintf(expected_line, sizeof(expected_line), "%08x : %08x", + 4*i, batch[i]); + igt_assert(strstr(line, expected_line)); + } + bb_ok = true; + continue; + } + + req_matched = sscanf(dashes, "--- %d requests\n", &requests); + if (req_matched == 1) { + igt_assert(strstr(ring_name, expected_ring_name)); + igt_assert(requests > 0); + + for (i = 0; i < requests; i++) { + uint32_t seqno; + long jiffies; + + igt_assert(getline(&line, &line_size, file) > 0); + items = sscanf(line, " seqno 0x%08x, emitted %ld, tail 0x%08x\n", + &seqno, &jiffies, &tail); + igt_assert(items == 3); + } + req_ok = true; + continue; + } + + ringbuf_matched = sscanf(dashes, "--- ringbuffer = 0x%08x\n", + >t_offset); + if (ringbuf_matched == 1) { + unsigned int offset, command, expected_addr = 0; + + if (!strstr(ring_name, expected_ring_name)) + continue; + igt_assert(req_ok); + + for (i = 0; i < tail / 4; i++) { + igt_assert(getline(&line, &line_size, file) > 0); + items = sscanf(line, "%08x : %08x\n", + &offset, &command); + igt_assert(items == 2); + if ((command & 0x1F800000) == MI_BATCH_BUFFER_START) { + igt_assert(getline(&line, &line_size, file) > 0); + items = sscanf(line, "%08x : %08x\n", + &offset, &expected_addr); + igt_assert(items == 2); + i++; + } + } + if (gen >= 4) + igt_assert(expected_addr == expected_offset); + else + igt_assert((expected_addr & ~0x1) == expected_offset); + ringbuf_ok = true; + continue; + } + + if (bb_ok && req_ok && ringbuf_ok) + break; + } + igt_assert(bb_ok && req_ok && ringbuf_ok); + + free(line); + free(ring_name); + close(debug_fd); +} + +static void test_error_state_capture(unsigned ring_id, + const char *ring_name) +{ + int fd, gen; + uint64_t offset; + + check_other_clients(); + clear_error_state(); + + fd = drm_open_any(); + gen = intel_gen(intel_get_drm_devid(fd)); + + offset = submit_batch(fd, ring_id, true); + close(fd); + + check_error_state(gen, ring_name, offset); +} + +static const struct target_ring { + const int id; + const char *short_name; + const char *full_name; +} rings[] = { + { I915_EXEC_RENDER, "render", "render ring" }, + { I915_EXEC_BSD, "bsd", "bsd ring" }, + { I915_EXEC_BLT, "blt", "blitter ring" }, + { I915_EXEC_VEBOX, "vebox", "video enhancement ring" }, +}; + +igt_main +{ + igt_skip_on_simulation(); + + igt_subtest("error-state-debugfs-entry") + test_debugfs_error_state_exists(); + + igt_subtest("error-state-sysfs-entry") + test_sysfs_error_exists(); + + igt_subtest("ring-stop-sysfs-entry") + test_debugfs_ring_stop_exists(); + + igt_subtest("error-state-basic") + test_error_state_basic(); + + for (int i = 0; i < sizeof(rings)/sizeof(rings[0]); i++) { + igt_subtest_f("error-state-capture-%s", rings[i].short_name) + test_error_state_capture(rings[i].id, rings[i].full_name); + } +} diff --git a/tests/drv_missed_irq_hang b/tests/drv_missed_irq_hang new file mode 100755 index 00000000..484e1514 --- /dev/null +++ b/tests/drv_missed_irq_hang @@ -0,0 +1,70 @@ +#!/bin/bash +# +# Testcase: Simulate missed breadcrumb interrupts +# + +SOURCE_DIR="$( dirname "${BASH_SOURCE[0]}" )" +. $SOURCE_DIR/drm_lib.sh + +oldpath=`pwd` + +cd $i915_dfs_path + +function check_for_missed_irq { + if test `cat i915_ring_missed_irq` = 0x00000000; then + echo "missed interrupts undetected" + exit 1 + fi +} + +function check_for_hang { + if cat i915_error_state | grep -v "no error state collected" > /dev/null ; then + echo "gpu hang reported" + exit 2 + fi +} + +if [ ! -f i915_ring_missed_irq ] ; then + echo "kernel doesn't support interrupt masking" + exit 77 +fi + +# clear error state first +echo > i915_error_state +check_for_hang + +echo 0xf > i915_ring_test_irq +echo "Interrupts masked" +if test `cat i915_ring_test_irq` != 0x0000000f; then + echo "Failed to set interrupt mask" + exit 3 +fi + +(cd $oldpath; $SOURCE_DIR/gem_exec_blt) > /dev/null + +check_for_missed_irq +check_for_hang + +(cd $oldpath; $SOURCE_DIR/gem_exec_blt) > /dev/null + +check_for_hang + +echo 0 > i915_ring_test_irq +echo "Interrupts unmasked" +if test `cat i915_ring_test_irq` != 0x00000000; then + echo "Failed to clear interrupt mask" + exit 3 +fi + +(cd $oldpath; $SOURCE_DIR/gem_exec_blt) > /dev/null + +check_for_hang + +echo 0 > i915_ring_missed_irq +echo "Cleared missed interrupts" +if test `cat i915_ring_missed_irq` != 0x00000000; then + echo "Failed to clear missed interrupts" + exit 3 +fi + +exit 0 diff --git a/tests/module_reload b/tests/drv_module_reload index 400fdd04..c1fd3957 100755 --- a/tests/module_reload +++ b/tests/drv_module_reload @@ -18,13 +18,18 @@ if ! echo 0 > /sys/class/vtconsole/vtcon1/bind ; then exit 77 fi +# The sound driver uses our power well +pkill alsactl +rmmod snd_hda_intel &> /dev/null + #ignore errors in ips - gen5 only rmmod intel_ips &> /dev/null rmmod i915 #ignore errors in intel-gtt, often built-in rmmod intel-gtt &> /dev/null -rmmod drm_kms_helper -rmmod drm +# drm may be used by other devices (nouveau, radeon, udl, etc) +rmmod drm_kms_helper &> /dev/null +rmmod drm &> /dev/null if lsmod | grep i915 &> /dev/null ; then echo WARNING: i915.ko still loaded! @@ -37,5 +42,9 @@ fi modprobe i915 echo 1 > /sys/class/vtconsole/vtcon1/bind +modprobe snd_hda_intel + # try to run something $SOURCE_DIR/gem_exec_nop > /dev/null && echo "module successfully loaded again" + +exit $exitcode diff --git a/tests/drv_suspend.c b/tests/drv_suspend.c new file mode 100644 index 00000000..80f6a225 --- /dev/null +++ b/tests/drv_suspend.c @@ -0,0 +1,189 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Daniel Vetter <daniel.vetter@ffwll.ch> + * + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/ioctl.h> + +#include <drm.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "igt_debugfs.h" +#include "igt_aux.h" + +#define OBJECT_SIZE (16*1024*1024) + +static void +test_fence_restore(int fd, bool tiled2untiled) +{ + uint32_t handle1, handle2, handle_tiled; + uint32_t *ptr1, *ptr2, *ptr_tiled; + int i; + + /* We wall the tiled object with untiled canary objects to make sure + * that we detect tile leaking in both directions. */ + handle1 = gem_create(fd, OBJECT_SIZE); + handle2 = gem_create(fd, OBJECT_SIZE); + handle_tiled = gem_create(fd, OBJECT_SIZE); + + /* Access the buffer objects in the order we want to have the laid out. */ + ptr1 = gem_mmap(fd, handle1, OBJECT_SIZE, PROT_READ | PROT_WRITE); + igt_assert(ptr1 != MAP_FAILED); + for (i = 0; i < OBJECT_SIZE/sizeof(uint32_t); i++) + ptr1[i] = i; + + ptr_tiled = gem_mmap(fd, handle_tiled, OBJECT_SIZE, PROT_READ | PROT_WRITE); + igt_assert(ptr_tiled != MAP_FAILED); + if (tiled2untiled) + gem_set_tiling(fd, handle_tiled, I915_TILING_X, 2048); + for (i = 0; i < OBJECT_SIZE/sizeof(uint32_t); i++) + ptr_tiled[i] = i; + + ptr2 = gem_mmap(fd, handle2, OBJECT_SIZE, PROT_READ | PROT_WRITE); + igt_assert(ptr2 != MAP_FAILED); + for (i = 0; i < OBJECT_SIZE/sizeof(uint32_t); i++) + ptr2[i] = i; + + if (tiled2untiled) + gem_set_tiling(fd, handle_tiled, I915_TILING_NONE, 2048); + else + gem_set_tiling(fd, handle_tiled, I915_TILING_X, 2048); + + igt_system_suspend_autoresume(); + + igt_info("checking the first canary object\n"); + for (i = 0; i < OBJECT_SIZE/sizeof(uint32_t); i++) + igt_assert(ptr1[i] == i); + + igt_info("checking the second canary object\n"); + for (i = 0; i < OBJECT_SIZE/sizeof(uint32_t); i++) + igt_assert(ptr2[i] == i); + + gem_close(fd, handle1); + gem_close(fd, handle2); + gem_close(fd, handle_tiled); + + munmap(ptr1, OBJECT_SIZE); + munmap(ptr2, OBJECT_SIZE); + munmap(ptr_tiled, OBJECT_SIZE); +} + +static void +test_debugfs_reader(void) +{ + struct igt_helper_process reader = {}; + reader.use_SIGKILL = true; + + igt_fork_helper(&reader) { + static const char dfs_base[] = "/sys/kernel/debug/dri"; + static char tmp[1024]; + + snprintf(tmp, sizeof(tmp) - 1, + "while true; do find %s/%i/ -type f | xargs cat > /dev/null 2>&1; done", + dfs_base, drm_get_card()); + igt_assert(execl("/bin/sh", "sh", "-c", tmp, (char *) NULL) != -1); + } + + sleep(1); + + igt_system_suspend_autoresume(); + + sleep(1); + + igt_stop_helper(&reader); +} + +static void +test_sysfs_reader(void) +{ + struct igt_helper_process reader = {}; + reader.use_SIGKILL = true; + + igt_fork_helper(&reader) { + static const char dfs_base[] = "/sys/class/drm/card"; + static char tmp[1024]; + + snprintf(tmp, sizeof(tmp) - 1, + "while true; do find %s%i*/ -type f | xargs cat > /dev/null 2>&1; done", + dfs_base, drm_get_card()); + igt_assert(execl("/bin/sh", "sh", "-c", tmp, (char *) NULL) != -1); + } + + sleep(1); + + igt_system_suspend_autoresume(); + + sleep(1); + + igt_stop_helper(&reader); +} + +static void +test_forcewake(void) +{ + int fw_fd; + + fw_fd = igt_open_forcewake_handle(); + igt_assert(fw_fd >= 0); + igt_system_suspend_autoresume(); + close (fw_fd); +} + +int fd; + +igt_main +{ + igt_skip_on_simulation(); + + igt_fixture + fd = drm_open_any(); + + igt_subtest("fence-restore-tiled2untiled") + test_fence_restore(fd, true); + + igt_subtest("fence-restore-untiled") + test_fence_restore(fd, false); + + igt_subtest("debugfs-reader") + test_debugfs_reader(); + + igt_subtest("sysfs-reader") + test_sysfs_reader(); + + igt_subtest("forcewake") + test_forcewake(); + + igt_fixture + close(fd); +} diff --git a/tests/eviction_common.c b/tests/eviction_common.c new file mode 100644 index 00000000..6c6eab46 --- /dev/null +++ b/tests/eviction_common.c @@ -0,0 +1,251 @@ +/* + * Copyright © 2007, 2011, 2013, 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * Daniel Vetter <daniel.vetter@ffwll.ch> + * Tvrtko Ursulin <tvrtko.ursulin@intel.com> + * + */ + +#include <stdlib.h> + +#include "drmtest.h" +#include "igt_aux.h" + +struct igt_eviction_test_ops +{ + uint32_t (*create)(int fd, int size); + void (*close)(int fd, uint32_t bo); + int (*copy)(int fd, uint32_t dst, uint32_t src, + uint32_t *all_bo, int nr_bos); + void (*clear)(int fd, uint32_t bo, int size); +}; + +#define FORKING_EVICTIONS_INTERRUPTIBLE (1 << 0) +#define FORKING_EVICTIONS_SWAPPING (1 << 1) +#define FORKING_EVICTIONS_DUP_DRMFD (1 << 2) +#define FORKING_EVICTIONS_MEMORY_PRESSURE (1 << 3) +#define ALL_FORKING_EVICTIONS (FORKING_EVICTIONS_INTERRUPTIBLE | \ + FORKING_EVICTIONS_SWAPPING | \ + FORKING_EVICTIONS_DUP_DRMFD | \ + FORKING_EVICTIONS_MEMORY_PRESSURE) + +static void exchange_uint32_t(void *array, unsigned i, unsigned j) +{ + uint32_t *i_arr = array; + uint32_t i_tmp; + + i_tmp = i_arr[i]; + i_arr[i] = i_arr[j]; + i_arr[j] = i_tmp; +} + +static int minor_evictions(int fd, struct igt_eviction_test_ops *ops, + int surface_size, int nr_surfaces) +{ + uint32_t *bo, *sel; + int n, m, pass, fail; + int total_surfaces; + + /* Make sure nr_surfaces is not divisible by seven + * to avoid duplicates in the selection loop below. + */ + nr_surfaces /= 7; + nr_surfaces *= 7; + nr_surfaces += 3; + + total_surfaces = gem_aperture_size(fd) / surface_size + 1; + igt_require(nr_surfaces < total_surfaces); + igt_require(intel_check_memory(total_surfaces, surface_size, CHECK_RAM)); + + bo = malloc((nr_surfaces + total_surfaces)*sizeof(*bo)); + igt_assert(bo); + + for (n = 0; n < total_surfaces; n++) + bo[n] = ops->create(fd, surface_size); + + sel = bo + n; + for (fail = 0, m = 0; fail < 10; fail++) { + int ret; + for (pass = 0; pass < 100; pass++) { + for (n = 0; n < nr_surfaces; n++, m += 7) + sel[n] = bo[m%total_surfaces]; + ret = ops->copy(fd, sel[0], sel[1], sel, nr_surfaces); + igt_assert(ret == 0); + } + ret = ops->copy(fd, bo[0], bo[0], bo, total_surfaces); + igt_assert(ret == ENOSPC); + } + + for (n = 0; n < total_surfaces; n++) + ops->close(fd, bo[n]); + free(bo); + + return 0; +} + +static int major_evictions(int fd, struct igt_eviction_test_ops *ops, + int surface_size, int nr_surfaces) +{ + int n, m, loop; + uint32_t *bo; + int ret; + + igt_require(intel_check_memory(nr_surfaces, surface_size, CHECK_RAM)); + + bo = malloc(nr_surfaces*sizeof(*bo)); + igt_assert(bo); + + for (n = 0; n < nr_surfaces; n++) + bo[n] = ops->create(fd, surface_size); + + for (loop = 0, m = 0; loop < 100; loop++, m += 17) { + n = m % nr_surfaces; + ret = ops->copy(fd, bo[n], bo[n], &bo[n], 1); + igt_assert(ret == 0); + } + + for (n = 0; n < nr_surfaces; n++) + ops->close(fd, bo[n]); + free(bo); + + return 0; +} + +static int swapping_evictions(int fd, struct igt_eviction_test_ops *ops, + int surface_size, + int working_surfaces, + int trash_surfaces) +{ + uint32_t *bo; + int i, n, pass, ret; + + igt_require(intel_check_memory(working_surfaces, surface_size, CHECK_RAM)); + + if (trash_surfaces < working_surfaces) + trash_surfaces = working_surfaces; + + igt_require(intel_check_memory(trash_surfaces, surface_size, CHECK_RAM | CHECK_SWAP)); + + bo = malloc(trash_surfaces*sizeof(*bo)); + igt_assert(bo); + + for (n = 0; n < trash_surfaces; n++) + bo[n] = ops->create(fd, surface_size); + + for (i = 0; i < trash_surfaces/32; i++) { + igt_permute_array(bo, trash_surfaces, exchange_uint32_t); + + for (pass = 0; pass < 100; pass++) { + ret = ops->copy(fd, bo[0], bo[1], bo, working_surfaces); + igt_assert(ret == 0); + } + } + + for (n = 0; n < trash_surfaces; n++) + ops->close(fd, bo[n]); + free(bo); + + return 0; +} + +#define min(a, b) ((a) < (b) ? (a) : (b)) + +static int forking_evictions(int fd, struct igt_eviction_test_ops *ops, + int surface_size, int working_surfaces, + int trash_surfaces, unsigned flags) +{ + uint32_t *bo; + int n, pass, l, ret; + int num_threads = sysconf(_SC_NPROCESSORS_ONLN); + int bo_count; + + igt_require(intel_check_memory(working_surfaces, surface_size, CHECK_RAM)); + + if (flags & FORKING_EVICTIONS_SWAPPING) { + bo_count = trash_surfaces; + if (bo_count < working_surfaces) + bo_count = working_surfaces; + + } else + bo_count = working_surfaces; + + igt_require(intel_check_memory(bo_count, surface_size, CHECK_RAM | CHECK_SWAP)); + + bo = malloc(bo_count*sizeof(*bo)); + igt_assert(bo); + + for (n = 0; n < bo_count; n++) + bo[n] = ops->create(fd, surface_size); + + igt_fork(i, min(num_threads * 4, 12)) { + int realfd = fd; + int num_passes = flags & FORKING_EVICTIONS_SWAPPING ? 10 : 100; + + /* Every fork should have a different permutation! */ + srand(i * 63); + + if (flags & FORKING_EVICTIONS_INTERRUPTIBLE) + igt_fork_signal_helper(); + + igt_permute_array(bo, bo_count, exchange_uint32_t); + + if (flags & FORKING_EVICTIONS_DUP_DRMFD) { + realfd = drm_open_any(); + + /* We can overwrite the bo array since we're forked. */ + for (l = 0; l < bo_count; l++) { + uint32_t flink; + + flink = gem_flink(fd, bo[l]); + bo[l] = gem_open(realfd, flink); + } + } + + for (pass = 0; pass < num_passes; pass++) { + ret = ops->copy(realfd, bo[0], bo[1], bo, working_surfaces); + igt_assert(ret == 0); + + for (l = 0; l < working_surfaces && + (flags & FORKING_EVICTIONS_MEMORY_PRESSURE); + l++) { + ops->clear(realfd, bo[l], surface_size); + } + } + + if (flags & FORKING_EVICTIONS_INTERRUPTIBLE) + igt_stop_signal_helper(); + + /* drmfd closing will take care of additional bo refs */ + if (flags & FORKING_EVICTIONS_DUP_DRMFD) + close(realfd); + } + + igt_waitchildren(); + + for (n = 0; n < bo_count; n++) + ops->close(fd, bo[n]); + free(bo); + + return 0; +} diff --git a/tests/flip_test.c b/tests/flip_test.c deleted file mode 100644 index 67105905..00000000 --- a/tests/flip_test.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright 2012 Intel Corporation - * Jesse Barnes <jesse.barnes@intel.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "config.h" - -#include <assert.h> -#include <cairo.h> -#include <errno.h> -#include <math.h> -#include <stdint.h> -#include <unistd.h> -#include <sys/poll.h> -#include <sys/time.h> -#include <sys/mman.h> -#include <sys/ioctl.h> - -#include "i915_drm.h" -#include "drmtest.h" -#include "testdisplay.h" - -drmModeRes *resources; -int drm_fd; -int test_time = 3; - -uint32_t *fb_ptr; - -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) - -struct type_name { - int type; - const char *name; -}; - -struct test_output { - uint32_t id; - int mode_valid; - drmModeModeInfo mode; - drmModeEncoder *encoder; - drmModeConnector *connector; - int crtc; - int pipe; - unsigned int current_fb_id; - unsigned int fb_ids[2]; -}; - -static void page_flip_handler(int fd, unsigned int frame, unsigned int sec, - unsigned int usec, void *data) -{ - struct test_output *o = data; - unsigned int new_fb_id; - - if (o->current_fb_id == o->fb_ids[0]) - new_fb_id = o->fb_ids[1]; - else - new_fb_id = o->fb_ids[0]; - - drmModePageFlip(drm_fd, o->crtc, new_fb_id, - DRM_MODE_PAGE_FLIP_EVENT, o); - o->current_fb_id = new_fb_id; -} - -static void connector_find_preferred_mode(struct test_output *o, int crtc_id) -{ - drmModeConnector *connector; - drmModeEncoder *encoder = NULL; - int i, j; - - /* First, find the connector & mode */ - o->mode_valid = 0; - o->crtc = 0; - connector = drmModeGetConnector(drm_fd, o->id); - assert(connector); - - if (connector->connection != DRM_MODE_CONNECTED) { - drmModeFreeConnector(connector); - return; - } - - if (!connector->count_modes) { - fprintf(stderr, "connector %d has no modes\n", o->id); - drmModeFreeConnector(connector); - return; - } - - if (connector->connector_id != o->id) { - fprintf(stderr, "connector id doesn't match (%d != %d)\n", - connector->connector_id, o->id); - drmModeFreeConnector(connector); - return; - } - - for (j = 0; j < connector->count_modes; j++) { - o->mode = connector->modes[j]; - if (o->mode.type & DRM_MODE_TYPE_PREFERRED) { - o->mode_valid = 1; - break; - } - } - - if (!o->mode_valid) { - if (connector->count_modes > 0) { - /* use the first mode as test mode */ - o->mode = connector->modes[0]; - o->mode_valid = 1; - } - else { - fprintf(stderr, "failed to find any modes on connector %d\n", - o->id); - return; - } - } - - /* Now get the encoder */ - for (i = 0; i < connector->count_encoders; i++) { - encoder = drmModeGetEncoder(drm_fd, connector->encoders[i]); - - if (!encoder) { - fprintf(stderr, "could not get encoder %i: %s\n", - resources->encoders[i], strerror(errno)); - drmModeFreeEncoder(encoder); - continue; - } - - break; - } - - o->encoder = encoder; - - if (i == resources->count_encoders) { - fprintf(stderr, "failed to find encoder\n"); - o->mode_valid = 0; - return; - } - - /* Find first CRTC not in use */ - for (i = 0; i < resources->count_crtcs; i++) { - if (resources->crtcs[i] != crtc_id) - continue; - if (resources->crtcs[i] && - (o->encoder->possible_crtcs & (1<<i))) { - o->crtc = resources->crtcs[i]; - break; - } - } - - if (!o->crtc) { - fprintf(stderr, "could not find requested crtc %d\n", crtc_id); - o->mode_valid = 0; - return; - } - - o->pipe = i; - - o->connector = connector; -} - -static void -paint_flip_mode(cairo_t *cr, int width, int height, void *priv) -{ - bool odd_frame = (bool) priv; - - if (odd_frame) - cairo_rectangle(cr, width/4, height/2, width/4, height/8); - else - cairo_rectangle(cr, width/2, height/2, width/4, height/8); - - cairo_set_source_rgb(cr, 1, 1, 1); - cairo_fill(cr); -} - -static void set_mode(struct test_output *o, int crtc) -{ - int ret; - int bpp = 32, depth = 24; - drmEventContext evctx; - int width, height; - struct timeval end; - struct kmstest_fb fb_info[2]; - - connector_find_preferred_mode(o, crtc); - if (!o->mode_valid) - return; - - width = o->mode.hdisplay; - height = o->mode.vdisplay; - - o->fb_ids[0] = kmstest_create_fb(drm_fd, width, height, bpp, depth, - false, &fb_info[0], - paint_flip_mode, (void *)false); - o->fb_ids[1] = kmstest_create_fb(drm_fd, width, height, bpp, depth, - false, &fb_info[1], - paint_flip_mode, (void *)true); - if (!o->fb_ids[0] || !o->fb_ids[1]) { - fprintf(stderr, "failed to create fbs\n"); - exit(3); - } - - gem_close(drm_fd, fb_info[0].gem_handle); - gem_close(drm_fd, fb_info[1].gem_handle); - - kmstest_dump_mode(&o->mode); - if (drmModeSetCrtc(drm_fd, o->crtc, o->fb_ids[0], 0, 0, - &o->id, 1, &o->mode)) { - fprintf(stderr, "failed to set mode (%dx%d@%dHz): %s\n", - width, height, o->mode.vrefresh, - strerror(errno)); - exit(3); - } - - ret = drmModePageFlip(drm_fd, o->crtc, o->fb_ids[1], - DRM_MODE_PAGE_FLIP_EVENT, o); - if (ret) { - fprintf(stderr, "failed to page flip: %s\n", strerror(errno)); - exit(4); - } - o->current_fb_id = o->fb_ids[1]; - - memset(&evctx, 0, sizeof evctx); - evctx.version = DRM_EVENT_CONTEXT_VERSION; - evctx.vblank_handler = NULL; - evctx.page_flip_handler = page_flip_handler; - - gettimeofday(&end, NULL); - end.tv_sec += 3; - - while (1) { - struct timeval now, timeout = { .tv_sec = 3, .tv_usec = 0 }; - fd_set fds; - - FD_ZERO(&fds); - FD_SET(0, &fds); - FD_SET(drm_fd, &fds); - ret = select(drm_fd + 1, &fds, NULL, NULL, &timeout); - - if (ret <= 0) { - fprintf(stderr, "select timed out or error (ret %d)\n", - ret); - exit(1); - } else if (FD_ISSET(0, &fds)) { - fprintf(stderr, "no fds active, breaking\n"); - exit(2); - } - - gettimeofday(&now, NULL); - if (now.tv_sec > end.tv_sec || - (now.tv_sec == end.tv_sec && now.tv_usec >= end.tv_usec)) { - ret = 0; - break; - } - - drmHandleEvent(drm_fd, &evctx); - } - - fprintf(stdout, "page flipping on crtc %d, connector %d: PASSED\n", - crtc, o->id); - - drmModeFreeEncoder(o->encoder); - drmModeFreeConnector(o->connector); -} - -static int run_test(void) -{ - struct test_output *connectors; - int c, i; - - resources = drmModeGetResources(drm_fd); - if (!resources) { - fprintf(stderr, "drmModeGetResources failed: %s\n", - strerror(errno)); - exit(5); - } - - connectors = calloc(resources->count_connectors, - sizeof(struct test_output)); - assert(connectors); - - /* Find any connected displays */ - for (c = 0; c < resources->count_connectors; c++) { - connectors[c].id = resources->connectors[c]; - for (i = 0; i < resources->count_crtcs; i++) - set_mode(&connectors[c], resources->crtcs[i]); - } - - drmModeFreeResources(resources); - return 1; -} - -int main(int argc, char **argv) -{ - drm_fd = drm_open_any(); - - run_test(); - - close(drm_fd); - - return 0; -} diff --git a/tests/gem_alive.c b/tests/gem_alive.c new file mode 100644 index 00000000..f87b1cbb --- /dev/null +++ b/tests/gem_alive.c @@ -0,0 +1,35 @@ +#include <sys/ioctl.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> +#include <signal.h> +#include <i915_drm.h> + +#include "drmtest.h" + +int main(void) +{ + struct drm_i915_gem_sw_finish arg = { 0 }; + int fd; + + signal(SIGALRM, SIG_IGN); + + fd = drm_open_any(); + if (fd < 0) + return IGT_EXIT_SKIP; + + alarm(1); + if (ioctl(fd, DRM_IOCTL_I915_GEM_SW_FINISH, &arg) == 0) + return IGT_EXIT_SKIP; + + switch (errno) { + case ENOENT: + return 0; + case EIO: + return 1; + case EINTR: + return 2; + default: + return 3; + } +} diff --git a/tests/gem_bad_address.c b/tests/gem_bad_address.c index fbb96497..f8fda90d 100644 --- a/tests/gem_bad_address.c +++ b/tests/gem_bad_address.c @@ -29,18 +29,18 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" +#include "intel_chipset.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; diff --git a/tests/gem_bad_batch.c b/tests/gem_bad_batch.c index db6636ae..33b3241f 100644 --- a/tests/gem_bad_batch.c +++ b/tests/gem_bad_batch.c @@ -29,18 +29,18 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_chipset.h" +#include "intel_io.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; diff --git a/tests/gem_bad_blit.c b/tests/gem_bad_blit.c index 22165270..9c031179 100644 --- a/tests/gem_bad_blit.c +++ b/tests/gem_bad_blit.c @@ -44,18 +44,18 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_chipset.h" +#include "intel_io.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; @@ -78,20 +78,18 @@ bad_blit(drm_intel_bo *src_bo, uint32_t devid) cmd_bits |= XY_SRC_COPY_BLT_DST_TILED; } - BEGIN_BATCH(8); - OUT_BATCH(XY_SRC_COPY_BLT_CMD | - XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB | - cmd_bits); + BLIT_COPY_BATCH_START(devid, cmd_bits); OUT_BATCH((3 << 24) | /* 32 bits */ (0xcc << 16) | /* copy ROP */ dst_pitch); OUT_BATCH(0); /* dst x1,y1 */ OUT_BATCH((64 << 16) | 64); /* 64x64 blit */ OUT_BATCH(BAD_GTT_DEST); + BLIT_RELOC_UDW(devid); OUT_BATCH(0); /* src x1,y1 */ OUT_BATCH(src_pitch); OUT_RELOC(src_bo, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(devid); ADVANCE_BATCH(); intel_batchbuffer_flush(batch); diff --git a/tests/gem_bad_length.c b/tests/gem_bad_length.c index 41f44d7f..11cc197a 100644 --- a/tests/gem_bad_length.c +++ b/tests/gem_bad_length.c @@ -29,19 +29,15 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/ioctl.h> -#include <sys/mman.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" -#define MI_BATCH_BUFFER_END (0xA<<23) - /* * Testcase: Minmal bo_create and batchbuffer exec * @@ -57,26 +53,29 @@ static uint32_t do_gem_create(int fd, int size, int *retval) create.handle = 0; create.size = (size + 4095) & -4096; ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create); - assert(retval || ret == 0); + igt_assert(retval || ret == 0); if (retval) *retval = errno; return create.handle; } +#if 0 static int gem_exec(int fd, struct drm_i915_gem_execbuffer2 *execbuf) { return drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf); } +#endif static void create0(int fd) { int retval = 0; - printf("trying to create a zero-length gem object\n"); + igt_info("trying to create a zero-length gem object\n"); do_gem_create(fd, 0, &retval); - assert(retval == EINVAL); + igt_assert(retval == EINVAL); } +#if 0 static void exec0(int fd) { struct drm_i915_gem_execbuffer2 execbuf; @@ -110,16 +109,19 @@ static void exec0(int fd) i915_execbuffer2_set_context_id(execbuf, 0); execbuf.rsvd2 = 0; - printf("trying to run an empty batchbuffer\n"); + igt_info("trying to run an empty batchbuffer\n"); gem_exec(fd, &execbuf); gem_close(fd, exec[0].handle); } +#endif -int main(int argc, char **argv) +igt_simple_main { int fd; + igt_skip_on_simulation(); + fd = drm_open_any(); create0(fd); @@ -127,6 +129,4 @@ int main(int argc, char **argv) //exec0(fd); close(fd); - - return 0; } diff --git a/tests/gem_bad_reloc.c b/tests/gem_bad_reloc.c new file mode 100644 index 00000000..26ebd11e --- /dev/null +++ b/tests/gem_bad_reloc.c @@ -0,0 +1,137 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Chris Wilson <chris@chris-wilson.co.uk> + * + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include "drm.h" +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_io.h" +#include "intel_chipset.h" + +#define USE_LUT (1 << 12) + +/* Simulates SNA behaviour using negative self-relocations for + * STATE_BASE_ADDRESS command packets. If they wrap around (to values greater + * than the total size of the GTT), the GPU will hang. + * See https://bugs.freedesktop.org/show_bug.cgi?id=78533 + */ +static int negative_reloc(int fd, unsigned flags) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 gem_exec[2]; + struct drm_i915_gem_relocation_entry gem_reloc[1000]; + uint64_t gtt_max = gem_aperture_size(fd); + uint32_t buf[1024] = {MI_BATCH_BUFFER_END}; + int i; + +#define BIAS (256*1024) + + igt_require(intel_gen(intel_get_drm_devid(fd)) >= 7); + + memset(gem_exec, 0, sizeof(gem_exec)); + gem_exec[0].handle = gem_create(fd, 4096); + gem_write(fd, gem_exec[0].handle, 0, buf, 8); + + gem_reloc[0].offset = 1024; + gem_reloc[0].delta = 0; + gem_reloc[0].target_handle = gem_exec[0].handle; + gem_reloc[0].read_domains = I915_GEM_DOMAIN_COMMAND; + + gem_exec[1].handle = gem_create(fd, 4096); + gem_write(fd, gem_exec[1].handle, 0, buf, 8); + gem_exec[1].relocation_count = 1; + gem_exec[1].relocs_ptr = (uintptr_t)gem_reloc; + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = (uintptr_t)gem_exec; + execbuf.buffer_count = 2; + execbuf.batch_len = 8; + + do_or_die(drmIoctl(fd, + DRM_IOCTL_I915_GEM_EXECBUFFER2, + &execbuf)); + gem_close(fd, gem_exec[1].handle); + + printf("Found offset %ld for 4k batch\n", (long)gem_exec[0].offset); + igt_require(gem_exec[0].offset < BIAS); + + memset(gem_reloc, 0, sizeof(gem_reloc)); + for (i = 0; i < sizeof(gem_reloc)/sizeof(gem_reloc[0]); i++) { + gem_reloc[i].offset = 8 + 4*i; + gem_reloc[i].delta = -BIAS*i/1024; + gem_reloc[i].target_handle = flags & USE_LUT ? 0 : gem_exec[0].handle; + gem_reloc[i].read_domains = I915_GEM_DOMAIN_COMMAND; + } + + gem_exec[0].relocation_count = sizeof(gem_reloc)/sizeof(gem_reloc[0]); + gem_exec[0].relocs_ptr = (uintptr_t)gem_reloc; + + execbuf.buffer_count = 1; + execbuf.flags = flags & USE_LUT; + do_or_die(drmIoctl(fd, + DRM_IOCTL_I915_GEM_EXECBUFFER2, + &execbuf)); + + printf("Batch is now at offset %ld\n", (long)gem_exec[0].offset); + + gem_read(fd, gem_exec[0].handle, 0, buf, sizeof(buf)); + gem_close(fd, gem_exec[0].handle); + + for (i = 0; i < sizeof(gem_reloc)/sizeof(gem_reloc[0]); i++) + igt_assert(buf[2 + i] < gtt_max); + + return 0; +} + +int fd; + +igt_main +{ + igt_fixture { + fd = drm_open_any(); + } + + igt_subtest("negative-reloc") + negative_reloc(fd, 0); + + igt_subtest("negative-reloc-lut") + negative_reloc(fd, USE_LUT); + + igt_fixture { + close(fd); + } +} diff --git a/tests/gem_basic.c b/tests/gem_basic.c index 24ad445f..f79b0669 100644 --- a/tests/gem_basic.c +++ b/tests/gem_basic.c @@ -29,14 +29,13 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/ioctl.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" static void @@ -45,12 +44,12 @@ test_bad_close(int fd) struct drm_gem_close close_bo; int ret; - printf("Testing error return on bad close ioctl.\n"); + igt_info("Testing error return on bad close ioctl.\n"); close_bo.handle = 0x10101010; ret = ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close_bo); - assert(ret == -1 && errno == EINVAL); + igt_assert(ret == -1 && errno == EINVAL); } static void @@ -58,7 +57,7 @@ test_create_close(int fd) { uint32_t handle; - printf("Testing creating and closing an object.\n"); + igt_info("Testing creating and closing an object.\n"); handle = gem_create(fd, 16*1024); @@ -68,7 +67,7 @@ test_create_close(int fd) static void test_create_fd_close(int fd) { - printf("Testing closing with an object allocated.\n"); + igt_info("Testing closing with an object allocated.\n"); gem_create(fd, 16*1024); /* leak it */ @@ -76,15 +75,17 @@ test_create_fd_close(int fd) close(fd); } -int main(int argc, char **argv) -{ - int fd; - - fd = drm_open_any(); +int fd; - test_bad_close(fd); - test_create_close(fd); - test_create_fd_close(fd); - - return 0; +igt_main +{ + igt_fixture + fd = drm_open_any(); + + igt_subtest("bad-close") + test_bad_close(fd); + igt_subtest("create-close") + test_create_close(fd); + igt_subtest("create-fd-close") + test_create_fd_close(fd); } diff --git a/tests/gem_caching.c b/tests/gem_caching.c new file mode 100644 index 00000000..e3692b8b --- /dev/null +++ b/tests/gem_caching.c @@ -0,0 +1,289 @@ +/* + * Copyright © 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Daniel Vetter <daniel.vetter@ffwll.ch> + * Chris Wilson <chris@chris-wilson.co.uk> + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> + +#include <drm.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_io.h" +#include "intel_chipset.h" +#include "igt_aux.h" + +/* + * Testcase: snoop consistency when touching partial cachelines + * + */ + +static drm_intel_bufmgr *bufmgr; +struct intel_batchbuffer *batch; + +drm_intel_bo *scratch_bo; +drm_intel_bo *staging_bo; +#define BO_SIZE (4*4096) +uint32_t devid; +uint64_t mappable_gtt_limit; +int fd; + +static void +copy_bo(drm_intel_bo *src, drm_intel_bo *dst) +{ + BLIT_COPY_BATCH_START(devid, 0); + OUT_BATCH((3 << 24) | /* 32 bits */ + (0xcc << 16) | /* copy ROP */ + 4096); + OUT_BATCH(0 << 16 | 0); + OUT_BATCH((BO_SIZE/4096) << 16 | 1024); + OUT_RELOC_FENCED(dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(devid); + OUT_BATCH(0 << 16 | 0); + OUT_BATCH(4096); + OUT_RELOC_FENCED(src, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(devid); + ADVANCE_BATCH(); + + intel_batchbuffer_flush(batch); +} + +static void +blt_bo_fill(drm_intel_bo *tmp_bo, drm_intel_bo *bo, uint8_t val) +{ + uint8_t *gtt_ptr; + int i; + + do_or_die(drm_intel_gem_bo_map_gtt(tmp_bo)); + gtt_ptr = tmp_bo->virtual; + + for (i = 0; i < BO_SIZE; i++) + gtt_ptr[i] = val; + + drm_intel_gem_bo_unmap_gtt(tmp_bo); + + if (bo->offset < mappable_gtt_limit && + (IS_G33(devid) || intel_gen(devid) >= 4)) + igt_trash_aperture(); + + copy_bo(tmp_bo, bo); +} + +#define MAX_BLT_SIZE 128 +#define ROUNDS 1000 +#define TEST_READ 0x1 +#define TEST_WRITE 0x2 +#define TEST_BOTH (TEST_READ | TEST_WRITE) +igt_main +{ + unsigned flags = TEST_BOTH; + int i, j; + uint8_t *cpu_ptr; + uint8_t *gtt_ptr; + + igt_skip_on_simulation(); + + igt_fixture { + srandom(0xdeadbeef); + + fd = drm_open_any(); + + gem_require_caching(fd); + + devid = intel_get_drm_devid(fd); + if (IS_GEN2(devid)) /* chipset only handles cached -> uncached */ + flags &= ~TEST_READ; + if (IS_BROADWATER(devid) || IS_CRESTLINE(devid)) { + /* chipset is completely fubar */ + igt_info("coherency broken on i965g/gm\n"); + flags = 0; + } + + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + batch = intel_batchbuffer_alloc(bufmgr, devid); + + /* overallocate the buffers we're actually using because */ + scratch_bo = drm_intel_bo_alloc(bufmgr, "scratch bo", BO_SIZE, 4096); + gem_set_caching(fd, scratch_bo->handle, 1); + + staging_bo = drm_intel_bo_alloc(bufmgr, "staging bo", BO_SIZE, 4096); + + igt_init_aperture_trashers(bufmgr); + mappable_gtt_limit = gem_mappable_aperture_size(); + } + + igt_subtest("reads") { + igt_require(flags & TEST_READ); + + igt_info("checking partial reads\n"); + + for (i = 0; i < ROUNDS; i++) { + uint8_t val0 = i; + int start, len; + + blt_bo_fill(staging_bo, scratch_bo, i); + + start = random() % BO_SIZE; + len = random() % (BO_SIZE-start) + 1; + + drm_intel_bo_map(scratch_bo, false); + cpu_ptr = scratch_bo->virtual; + for (j = 0; j < len; j++) { + igt_assert_f(cpu_ptr[j] == val0, + "mismatch at %i, got: %i, expected: %i\n", + j, cpu_ptr[j], val0); + } + drm_intel_bo_unmap(scratch_bo); + + igt_progress("partial reads test: ", i, ROUNDS); + } + } + + igt_subtest("writes") { + igt_require(flags & TEST_WRITE); + + igt_info("checking partial writes\n"); + + for (i = 0; i < ROUNDS; i++) { + uint8_t val0 = i, val1; + int start, len; + + blt_bo_fill(staging_bo, scratch_bo, val0); + + start = random() % BO_SIZE; + len = random() % (BO_SIZE-start) + 1; + + val1 = val0 + 63; + drm_intel_bo_map(scratch_bo, true); + cpu_ptr = scratch_bo->virtual; + memset(cpu_ptr + start, val1, len); + drm_intel_bo_unmap(scratch_bo); + + copy_bo(scratch_bo, staging_bo); + do_or_die(drm_intel_gem_bo_map_gtt(staging_bo)); + gtt_ptr = staging_bo->virtual; + + for (j = 0; j < start; j++) { + igt_assert_f(gtt_ptr[j] == val0, + "mismatch at %i, partial=[%d+%d] got: %i, expected: %i\n", + j, start, len, gtt_ptr[j], val0); + } + for (; j < start + len; j++) { + igt_assert_f(gtt_ptr[j] == val1, + "mismatch at %i, partial=[%d+%d] got: %i, expected: %i\n", + j, start, len, gtt_ptr[j], val1); + } + for (; j < BO_SIZE; j++) { + igt_assert_f(gtt_ptr[j] == val0, + "mismatch at %i, partial=[%d+%d] got: %i, expected: %i\n", + j, start, len, gtt_ptr[j], val0); + } + drm_intel_gem_bo_unmap_gtt(staging_bo); + + igt_progress("partial writes test: ", i, ROUNDS); + } + } + + igt_subtest("read-writes") { + igt_require((flags & TEST_BOTH) == TEST_BOTH); + + igt_info("checking partial writes after partial reads\n"); + + for (i = 0; i < ROUNDS; i++) { + uint8_t val0 = i, val1, val2; + int start, len; + + blt_bo_fill(staging_bo, scratch_bo, val0); + + /* partial read */ + start = random() % BO_SIZE; + len = random() % (BO_SIZE-start) + 1; + + do_or_die(drm_intel_bo_map(scratch_bo, false)); + cpu_ptr = scratch_bo->virtual; + for (j = 0; j < len; j++) { + igt_assert_f(cpu_ptr[j] == val0, + "mismatch in read at %i, got: %i, expected: %i\n", + j, cpu_ptr[j], val0); + } + drm_intel_bo_unmap(scratch_bo); + + /* Change contents through gtt to make the pread cachelines + * stale. */ + val1 = i + 17; + blt_bo_fill(staging_bo, scratch_bo, val1); + + /* partial write */ + start = random() % BO_SIZE; + len = random() % (BO_SIZE-start) + 1; + + val2 = i + 63; + do_or_die(drm_intel_bo_map(scratch_bo, false)); + cpu_ptr = scratch_bo->virtual; + memset(cpu_ptr + start, val2, len); + + copy_bo(scratch_bo, staging_bo); + do_or_die(drm_intel_gem_bo_map_gtt(staging_bo)); + gtt_ptr = staging_bo->virtual; + + for (j = 0; j < start; j++) { + igt_assert_f(gtt_ptr[j] == val1, + "mismatch at %i, partial=[%d+%d] got: %i, expected: %i\n", + j, start, len, gtt_ptr[j], val1); + } + for (; j < start + len; j++) { + igt_assert_f(gtt_ptr[j] == val2, + "mismatch at %i, partial=[%d+%d] got: %i, expected: %i\n", + j, start, len, gtt_ptr[j], val2); + } + for (; j < BO_SIZE; j++) { + igt_assert_f(gtt_ptr[j] == val1, + "mismatch at %i, partial=[%d+%d] got: %i, expected: %i\n", + j, start, len, gtt_ptr[j], val1); + } + drm_intel_gem_bo_unmap_gtt(staging_bo); + drm_intel_bo_unmap(scratch_bo); + + igt_progress("partial read/writes test: ", i, ROUNDS); + } + } + + igt_fixture { + igt_cleanup_aperture_trashers(); + drm_intel_bufmgr_destroy(bufmgr); + + close(fd); + } +} diff --git a/tests/gem_close_race.c b/tests/gem_close_race.c new file mode 100644 index 00000000..e46e2c15 --- /dev/null +++ b/tests/gem_close_race.c @@ -0,0 +1,280 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Chris Wilson <chris@chris-wilson.co.uk> + * + */ + +#include <pthread.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include "drm.h" +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_chipset.h" + +#define OBJECT_SIZE 1024*1024*4 + +#define COPY_BLT_CMD (2<<29|0x53<<22|0x6) +#define BLT_WRITE_ALPHA (1<<21) +#define BLT_WRITE_RGB (1<<20) + +static char device[80]; +static uint32_t devid; +static bool has_64bit_relocations; + +static void selfcopy(int fd, uint32_t handle, int loops) +{ + struct drm_i915_gem_relocation_entry reloc[2]; + struct drm_i915_gem_exec_object2 gem_exec[2]; + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_pwrite gem_pwrite; + struct drm_i915_gem_create create; + uint32_t buf[12], *b = buf; + + memset(reloc, 0, sizeof(reloc)); + memset(gem_exec, 0, sizeof(gem_exec)); + memset(&execbuf, 0, sizeof(execbuf)); + + *b = COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB; + if (has_64bit_relocations) + *b += 2; + b++; + *b++ = 0xcc << 16 | 1 << 25 | 1 << 24 | (4*1024); + *b++ = 0; + *b++ = 512 << 16 | 1024; + + reloc[0].offset = (b - buf) * sizeof(*b); + reloc[0].target_handle = handle; + reloc[0].read_domains = I915_GEM_DOMAIN_RENDER; + reloc[0].write_domain = I915_GEM_DOMAIN_RENDER; + *b++ = 0; + if (has_64bit_relocations) + *b++ = 0; + + *b++ = 512 << 16; + *b++ = 4*1024; + + reloc[1].offset = (b - buf) * sizeof(*b); + reloc[1].target_handle = handle; + reloc[1].read_domains = I915_GEM_DOMAIN_RENDER; + reloc[1].write_domain = 0; + *b++ = 0; + if (has_64bit_relocations) + *b++ = 0; + + *b++ = MI_BATCH_BUFFER_END; + *b++ = 0; + + gem_exec[0].handle = handle; + + create.handle = 0; + create.size = 4096; + drmIoctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create); + gem_exec[1].handle = create.handle; + gem_exec[1].relocation_count = 2; + gem_exec[1].relocs_ptr = (uintptr_t)reloc; + + execbuf.buffers_ptr = (uintptr_t)gem_exec; + execbuf.buffer_count = 2; + execbuf.batch_len = (b - buf) * sizeof(*b); + if (HAS_BLT_RING(devid)) + execbuf.flags |= I915_EXEC_BLT; + + gem_pwrite.handle = gem_exec[1].handle; + gem_pwrite.offset = 0; + gem_pwrite.size = execbuf.batch_len; + gem_pwrite.data_ptr = (uintptr_t)buf; + if (drmIoctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &gem_pwrite) == 0) { + while (loops--) + drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + } + + drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &create.handle); +} + +static uint32_t load(int fd) +{ + uint32_t handle; + + handle = gem_create(fd, OBJECT_SIZE); + if (handle == 0) + return 0; + + selfcopy(fd, handle, 30); + return handle; +} + +static void run(int child) +{ + uint32_t handle; + int fd; + + fd = open(device, O_RDWR); + igt_assert(fd != -1); + + handle = load(fd); + if ((child & 63) == 63) + gem_read(fd, handle, 0, &handle, sizeof(handle)); +} + +#define NUM_FD 768 + +struct thread { + pthread_mutex_t mutex; + int fds[NUM_FD]; + int done; +}; + +static void *thread_run(void *_data) +{ + struct thread *t = _data; + + pthread_mutex_lock(&t->mutex); + while (!t->done) { + pthread_mutex_unlock(&t->mutex); + + for (int n = 0; n < NUM_FD; n++) { + struct drm_i915_gem_create create; + + create.handle = 0; + create.size = OBJECT_SIZE; + drmIoctl(t->fds[n], DRM_IOCTL_I915_GEM_CREATE, &create); + if (create.handle == 0) + continue; + + selfcopy(t->fds[n], create.handle, 10); + + drmIoctl(t->fds[n], DRM_IOCTL_GEM_CLOSE, &create.handle); + } + + pthread_mutex_lock(&t->mutex); + } + pthread_mutex_unlock(&t->mutex); + + return 0; +} + +static void *thread_busy(void *_data) +{ + struct thread *t = _data; + int n; + + pthread_mutex_lock(&t->mutex); + while (!t->done) { + struct drm_i915_gem_create create; + struct drm_i915_gem_busy busy; + + pthread_mutex_unlock(&t->mutex); + + n = rand() % NUM_FD; + + create.handle = 0; + create.size = OBJECT_SIZE; + drmIoctl(t->fds[n], DRM_IOCTL_I915_GEM_CREATE, &create); + if (create.handle == 0) + continue; + + selfcopy(t->fds[n], create.handle, 1); + + busy.handle = create.handle; + drmIoctl(t->fds[n], DRM_IOCTL_I915_GEM_BUSY, &busy); + + drmIoctl(t->fds[n], DRM_IOCTL_GEM_CLOSE, &create.handle); + + usleep(10*1000); + + pthread_mutex_lock(&t->mutex); + } + pthread_mutex_unlock(&t->mutex); + + return 0; +} + +igt_main +{ + igt_skip_on_simulation(); + + igt_fixture { + int fd; + + sprintf(device, "/dev/dri/card%d", drm_get_card()); + fd = open(device, O_RDWR); + + igt_assert(fd != -1); + devid = intel_get_drm_devid(fd); + has_64bit_relocations = intel_gen(devid) >= 8; + close(fd); + } + + igt_subtest("process-exit") { + igt_fork(child, NUM_FD) + run(child); + igt_waitchildren(); + } + + igt_subtest("gem-close-race") { + pthread_t thread[2]; + struct thread *data = calloc(1, sizeof(struct thread)); + int n; + + igt_assert(data); + + pthread_mutex_init(&data->mutex, NULL); + for (n = 0; n < NUM_FD; n++) + data->fds[n] = open(device, O_RDWR); + + pthread_create(&thread[0], NULL, thread_run, data); + pthread_create(&thread[1], NULL, thread_busy, data); + + for (n = 0; n < 1000*NUM_FD; n++) { + int i = rand() % NUM_FD; + if (data->fds[i] == -1) { + data->fds[i] = open(device, O_RDWR); + } else{ + close(data->fds[i]); + data->fds[i] = -1; + } + } + + pthread_mutex_lock(&data->mutex); + data->done = 1; + pthread_mutex_unlock(&data->mutex); + + pthread_join(thread[1], NULL); + pthread_join(thread[0], NULL); + + for (n = 0; n < NUM_FD; n++) + close(data->fds[n]); + free(data); + } +} diff --git a/tests/gem_concurrent_blit.c b/tests/gem_concurrent_blit.c new file mode 100644 index 00000000..61b1c2a0 --- /dev/null +++ b/tests/gem_concurrent_blit.c @@ -0,0 +1,398 @@ +/* + * Copyright © 2009,2012,2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * Chris Wilson <chris@chris-wilson.co.uk> + * Daniel Vetter <daniel.vetter@ffwll.ch> + * + */ + +/** @file gem_concurrent_blit.c + * + * This is a test of pread/pwrite behavior when writing to active + * buffers. + * + * Based on gem_gtt_concurrent_blt. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/wait.h> + +#include <drm.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_io.h" +#include "intel_chipset.h" +#include "igt_aux.h" + +static void +prw_set_bo(drm_intel_bo *bo, uint32_t val, int width, int height) +{ + int size = width * height, i; + uint32_t *tmp; + + tmp = malloc(4*size); + if (tmp) { + for (i = 0; i < size; i++) + tmp[i] = val; + drm_intel_bo_subdata(bo, 0, 4*size, tmp); + free(tmp); + } else { + for (i = 0; i < size; i++) + drm_intel_bo_subdata(bo, 4*i, 4, &val); + } +} + +static void +prw_cmp_bo(drm_intel_bo *bo, uint32_t val, int width, int height) +{ + int size = width * height, i; + uint32_t *tmp; + + tmp = malloc(4*size); + if (tmp) { + memset(tmp, 0, 4*size); + do_or_die(drm_intel_bo_get_subdata(bo, 0, 4*size, tmp)); + for (i = 0; i < size; i++) + igt_assert(tmp[i] == val); + free(tmp); + } else { + uint32_t t; + for (i = 0; i < size; i++) { + t = 0; + do_or_die(drm_intel_bo_get_subdata(bo, 4*i, 4, &t)); + igt_assert(t == val); + } + } +} + +static drm_intel_bo * +unmapped_create_bo(drm_intel_bufmgr *bufmgr, uint32_t val, int width, int height) +{ + drm_intel_bo *bo; + + bo = drm_intel_bo_alloc(bufmgr, "bo", 4*width*height, 0); + igt_assert(bo); + + return bo; +} + +static void +gtt_set_bo(drm_intel_bo *bo, uint32_t val, int width, int height) +{ + int size = width * height; + uint32_t *vaddr; + + drm_intel_gem_bo_start_gtt_access(bo, true); + vaddr = bo->virtual; + while (size--) + *vaddr++ = val; +} + +static void +gtt_cmp_bo(drm_intel_bo *bo, uint32_t val, int width, int height) +{ + int size = width * height; + uint32_t *vaddr; + + drm_intel_gem_bo_start_gtt_access(bo, false); + vaddr = bo->virtual; + while (size--) + igt_assert(*vaddr++ == val); +} + +static drm_intel_bo * +gtt_create_bo(drm_intel_bufmgr *bufmgr, uint32_t val, int width, int height) +{ + drm_intel_bo *bo; + + bo = drm_intel_bo_alloc(bufmgr, "bo", 4*width*height, 0); + igt_assert(bo); + + /* gtt map doesn't have a write parameter, so just keep the mapping + * around (to avoid the set_domain with the gtt write domain set) and + * manually tell the kernel when we start access the gtt. */ + do_or_die(drm_intel_gem_bo_map_gtt(bo)); + + return bo; +} + +static void +cpu_set_bo(drm_intel_bo *bo, uint32_t val, int width, int height) +{ + int size = width * height; + uint32_t *vaddr; + + do_or_die(drm_intel_bo_map(bo, true)); + vaddr = bo->virtual; + while (size--) + *vaddr++ = val; + drm_intel_bo_unmap(bo); +} + +static void +cpu_cmp_bo(drm_intel_bo *bo, uint32_t val, int width, int height) +{ + int size = width * height; + uint32_t *vaddr; + + do_or_die(drm_intel_bo_map(bo, false)); + vaddr = bo->virtual; + while (size--) + igt_assert(*vaddr++ == val); + drm_intel_bo_unmap(bo); +} + +struct access_mode { + void (*set_bo)(drm_intel_bo *bo, uint32_t val, int w, int h); + void (*cmp_bo)(drm_intel_bo *bo, uint32_t val, int w, int h); + drm_intel_bo *(*create_bo)(drm_intel_bufmgr *bufmgr, + uint32_t val, int width, int height); + const char *name; +}; + +struct access_mode access_modes[] = { + { .set_bo = prw_set_bo, .cmp_bo = prw_cmp_bo, + .create_bo = unmapped_create_bo, .name = "prw" }, + { .set_bo = cpu_set_bo, .cmp_bo = cpu_cmp_bo, + .create_bo = unmapped_create_bo, .name = "cpu" }, + { .set_bo = gtt_set_bo, .cmp_bo = gtt_cmp_bo, + .create_bo = gtt_create_bo, .name = "gtt" }, +}; + +#define MAX_NUM_BUFFERS 1024 +int num_buffers = MAX_NUM_BUFFERS, fd; +drm_intel_bufmgr *bufmgr; +struct intel_batchbuffer *batch; +int width = 512, height = 512; + +static void do_overwrite_source(struct access_mode *mode, + drm_intel_bo **src, drm_intel_bo **dst, + drm_intel_bo *dummy) +{ + int i; + + gem_quiescent_gpu(fd); + for (i = 0; i < num_buffers; i++) { + mode->set_bo(src[i], i, width, height); + mode->set_bo(dst[i], i, width, height); + } + for (i = 0; i < num_buffers; i++) + intel_copy_bo(batch, dst[i], src[i], width*height*4); + for (i = num_buffers; i--; ) + mode->set_bo(src[i], 0xdeadbeef, width, height); + for (i = 0; i < num_buffers; i++) + mode->cmp_bo(dst[i], i, width, height); +} + +static void do_early_read(struct access_mode *mode, + drm_intel_bo **src, drm_intel_bo **dst, + drm_intel_bo *dummy) +{ + int i; + + gem_quiescent_gpu(fd); + for (i = num_buffers; i--; ) + mode->set_bo(src[i], 0xdeadbeef, width, height); + for (i = 0; i < num_buffers; i++) + intel_copy_bo(batch, dst[i], src[i], width*height*4); + for (i = num_buffers; i--; ) + mode->cmp_bo(dst[i], 0xdeadbeef, width, height); +} + +static void do_gpu_read_after_write(struct access_mode *mode, + drm_intel_bo **src, drm_intel_bo **dst, + drm_intel_bo *dummy) +{ + int i; + + gem_quiescent_gpu(fd); + for (i = num_buffers; i--; ) + mode->set_bo(src[i], 0xabcdabcd, width, height); + for (i = 0; i < num_buffers; i++) + intel_copy_bo(batch, dst[i], src[i], width*height*4); + for (i = num_buffers; i--; ) + intel_copy_bo(batch, dummy, dst[i], width*height*4); + for (i = num_buffers; i--; ) + mode->cmp_bo(dst[i], 0xabcdabcd, width, height); +} + +typedef void (*do_test)(struct access_mode *mode, + drm_intel_bo **src, drm_intel_bo **dst, + drm_intel_bo *dummy); + +typedef void (*run_wrap)(struct access_mode *mode, + drm_intel_bo **src, drm_intel_bo **dst, + drm_intel_bo *dummy, + do_test do_test_func); + +static void run_single(struct access_mode *mode, + drm_intel_bo **src, drm_intel_bo **dst, + drm_intel_bo *dummy, + do_test do_test_func) +{ + do_test_func(mode, src, dst, dummy); +} + + +static void run_interruptible(struct access_mode *mode, + drm_intel_bo **src, drm_intel_bo **dst, + drm_intel_bo *dummy, + do_test do_test_func) +{ + int loop; + + igt_fork_signal_helper(); + + for (loop = 0; loop < 10; loop++) + do_test_func(mode, src, dst, dummy); + + igt_stop_signal_helper(); +} + +static void run_forked(struct access_mode *mode, + drm_intel_bo **src, drm_intel_bo **dst, + drm_intel_bo *dummy, + do_test do_test_func) +{ + const int old_num_buffers = num_buffers; + + num_buffers /= 16; + num_buffers += 2; + + igt_fork_signal_helper(); + + igt_fork(child, 16) { + /* recreate process local variables */ + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + drm_intel_bufmgr_gem_enable_reuse(bufmgr); + batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); + for (int i = 0; i < num_buffers; i++) { + src[i] = mode->create_bo(bufmgr, i, width, height); + dst[i] = mode->create_bo(bufmgr, ~i, width, height); + } + dummy = mode->create_bo(bufmgr, 0, width, height); + for (int loop = 0; loop < 10; loop++) + do_test_func(mode, src, dst, dummy); + /* as we borrow the fd, we need to reap our bo */ + for (int i = 0; i < num_buffers; i++) { + drm_intel_bo_unreference(src[i]); + drm_intel_bo_unreference(dst[i]); + } + drm_intel_bo_unreference(dummy); + intel_batchbuffer_free(batch); + drm_intel_bufmgr_destroy(bufmgr); + } + + igt_waitchildren(); + + igt_stop_signal_helper(); + + num_buffers = old_num_buffers; +} + +static void +run_basic_modes(struct access_mode *mode, + drm_intel_bo **src, drm_intel_bo **dst, + drm_intel_bo *dummy, const char *suffix, + run_wrap run_wrap_func) +{ + /* try to overwrite the source values */ + igt_subtest_f("%s-overwrite-source%s", mode->name, suffix) + run_wrap_func(mode, src, dst, dummy, do_overwrite_source); + + /* try to read the results before the copy completes */ + igt_subtest_f("%s-early-read%s", mode->name, suffix) + run_wrap_func(mode, src, dst, dummy, do_early_read); + + /* and finally try to trick the kernel into loosing the pending write */ + igt_subtest_f("%s-gpu-read-after-write%s", mode->name, suffix) + run_wrap_func(mode, src, dst, dummy, do_gpu_read_after_write); +} + +static void +run_modes(struct access_mode *mode) +{ + drm_intel_bo *src[MAX_NUM_BUFFERS], *dst[MAX_NUM_BUFFERS], *dummy = NULL; + + igt_fixture { + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + drm_intel_bufmgr_gem_enable_reuse(bufmgr); + batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); + + for (int i = 0; i < num_buffers; i++) { + src[i] = mode->create_bo(bufmgr, i, width, height); + dst[i] = mode->create_bo(bufmgr, ~i, width, height); + } + dummy = mode->create_bo(bufmgr, 0, width, height); + } + + run_basic_modes(mode, src, dst, dummy, "", run_single); + run_basic_modes(mode, src, dst, dummy, "-interruptible", run_interruptible); + + igt_fixture { + for (int i = 0; i < num_buffers; i++) { + drm_intel_bo_unreference(src[i]); + drm_intel_bo_unreference(dst[i]); + } + drm_intel_bo_unreference(dummy); + intel_batchbuffer_free(batch); + drm_intel_bufmgr_destroy(bufmgr); + } + + run_basic_modes(mode, src, dst, dummy, "-forked", run_forked); +} + +igt_main +{ + int max, i; + + igt_skip_on_simulation(); + + igt_fixture { + fd = drm_open_any(); + + max = gem_aperture_size (fd) / (1024 * 1024) / 2; + if (num_buffers > max) + num_buffers = max; + + max = intel_get_total_ram_mb() * 3 / 4; + if (num_buffers > max) + num_buffers = max; + num_buffers /= 2; + igt_info("using 2x%d buffers, each 1MiB\n", num_buffers); + } + + for (i = 0; i < ARRAY_SIZE(access_modes); i++) + run_modes(&access_modes[i]); +} diff --git a/tests/gem_cpu_concurrent_blit.c b/tests/gem_cpu_concurrent_blit.c deleted file mode 100644 index fd517d00..00000000 --- a/tests/gem_cpu_concurrent_blit.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright © 2009,2012 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * Authors: - * Eric Anholt <eric@anholt.net> - * Chris Wilson <chris@chris-wilson.co.uk> - * - */ - -/** @file gem_cpu_concurrent_blit.c - * - * This is a test of CPU read/write behavior when writing to active - * buffers. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <assert.h> -#include <fcntl.h> -#include <inttypes.h> -#include <errno.h> -#include <sys/stat.h> -#include <sys/time.h> -#include "drm.h" -#include "i915_drm.h" -#include "drmtest.h" -#include "intel_bufmgr.h" -#include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" - -static void -set_bo(drm_intel_bo *bo, uint32_t val, int width, int height) -{ - int size = width * height; - uint32_t *vaddr; - - drm_intel_bo_map(bo, true); - vaddr = bo->virtual; - while (size--) - *vaddr++ = val; - drm_intel_bo_unmap(bo); -} - -static void -cmp_bo(drm_intel_bo *bo, uint32_t val, int width, int height) -{ - int size = width * height; - uint32_t *vaddr; - - drm_intel_bo_map(bo, false); - vaddr = bo->virtual; - while (size--) - assert(*vaddr++ == val); - drm_intel_bo_unmap(bo); -} - -static drm_intel_bo * -create_bo(drm_intel_bufmgr *bufmgr, uint32_t val, int width, int height) -{ - drm_intel_bo *bo; - - bo = drm_intel_bo_alloc(bufmgr, "bo", 4*width*height, 0); - assert(bo); - - set_bo(bo, val, width, height); - - return bo; -} - -int -main(int argc, char **argv) -{ - drm_intel_bufmgr *bufmgr; - struct intel_batchbuffer *batch; - int num_buffers = 128, max; - drm_intel_bo *src[128], *dst[128], *dummy; - int width = 512, height = 512; - int fd; - int i; - - fd = drm_open_any(); - - max = gem_aperture_size (fd) / (1024 * 1024) / 2; - if (num_buffers > max) - num_buffers = max; - - bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - drm_intel_bufmgr_gem_enable_reuse(bufmgr); - batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); - - for (i = 0; i < num_buffers; i++) { - src[i] = create_bo(bufmgr, i, width, height); - dst[i] = create_bo(bufmgr, ~i, width, height); - } - dummy = create_bo(bufmgr, 0, width, height); - - /* try to overwrite the source values */ - for (i = 0; i < num_buffers; i++) - intel_copy_bo(batch, dst[i], src[i], width, height); - for (i = num_buffers; i--; ) - set_bo(src[i], 0xdeadbeef, width, height); - for (i = 0; i < num_buffers; i++) - cmp_bo(dst[i], i, width, height); - - /* try to read the results before the copy completes */ - for (i = 0; i < num_buffers; i++) - intel_copy_bo(batch, dst[i], src[i], width, height); - for (i = num_buffers; i--; ) - cmp_bo(dst[i], 0xdeadbeef, width, height); - - /* and finally try to trick the kernel into loosing the pending write */ - for (i = num_buffers; i--; ) - set_bo(src[i], 0xabcdabcd, width, height); - for (i = 0; i < num_buffers; i++) - intel_copy_bo(batch, dst[i], src[i], width, height); - for (i = num_buffers; i--; ) - intel_copy_bo(batch, dummy, dst[i], width, height); - for (i = num_buffers; i--; ) - cmp_bo(dst[i], 0xabcdabcd, width, height); - - return 0; -} diff --git a/tests/gem_cpu_reloc.c b/tests/gem_cpu_reloc.c new file mode 100644 index 00000000..46183231 --- /dev/null +++ b/tests/gem_cpu_reloc.c @@ -0,0 +1,247 @@ +/* + * Copyright © 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Chris Wilson <chris@chris-wilson.co.uk> + * + */ + +/* + * Testcase: Test the relocations through the CPU domain + * + * Attempt to stress test performing relocations whilst the batch is in the + * CPU domain. + * + * A freshly allocated buffer starts in the CPU domain, and the pwrite + * should also be performed whilst in the CPU domain and so we should + * execute the relocations within the CPU domain. If for any reason one of + * those steps should land it in the GTT domain, we take the secondary + * precaution of filling the mappable portion of the GATT. + * + * In order to detect whether a relocation fails, we first fill a target + * buffer with a sequence of invalid commands that would cause the GPU to + * immediate hang, and then attempt to overwrite them with a legal, if + * short, batchbuffer using a BLT. Then we come to execute the bo, if the + * relocation fail and we either copy across all zeros or garbage, then the + * GPU will hang. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> + +#include <drm.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_io.h" +#include "intel_chipset.h" +#include "igt_aux.h" + +static uint32_t use_blt; + +static void copy(int fd, uint32_t batch, uint32_t src, uint32_t dst) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_relocation_entry gem_reloc[2]; + struct drm_i915_gem_exec_object2 gem_exec[3]; + + gem_reloc[0].offset = 4 * sizeof(uint32_t); + gem_reloc[0].delta = 0; + gem_reloc[0].target_handle = dst; + gem_reloc[0].read_domains = I915_GEM_DOMAIN_RENDER; + gem_reloc[0].write_domain = I915_GEM_DOMAIN_RENDER; + gem_reloc[0].presumed_offset = 0; + + gem_reloc[1].offset = 7 * sizeof(uint32_t); + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + gem_reloc[1].offset += sizeof(uint32_t); + gem_reloc[1].delta = 0; + gem_reloc[1].target_handle = src; + gem_reloc[1].read_domains = I915_GEM_DOMAIN_RENDER; + gem_reloc[1].write_domain = 0; + gem_reloc[1].presumed_offset = 0; + + memset(gem_exec, 0, sizeof(gem_exec)); + gem_exec[0].handle = src; + gem_exec[1].handle = dst; + gem_exec[2].handle = batch; + gem_exec[2].relocation_count = 2; + gem_exec[2].relocs_ptr = (uintptr_t)gem_reloc; + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = (uintptr_t)gem_exec; + execbuf.buffer_count = 3; + execbuf.batch_len = 4096; + execbuf.flags = use_blt; + + do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf)); +} + +static void exec(int fd, uint32_t handle) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 gem_exec; + + memset(&gem_exec, 0, sizeof(gem_exec)); + gem_exec.handle = handle; + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = (uintptr_t)&gem_exec; + execbuf.buffer_count = 1; + execbuf.batch_len = 4096; + + do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf)); +} + +uint32_t gen6_batch[] = { + (XY_SRC_COPY_BLT_CMD | 6 | + XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB), + (3 << 24 | /* 32 bits */ + 0xcc << 16 | /* copy ROP */ + 4096), + 0 << 16 | 0, /* dst x1, y1 */ + 1 << 16 | 2, + 0, /* dst relocation */ + 0 << 16 | 0, /* src x1, y1 */ + 4096, + 0, /* src relocation */ + MI_BATCH_BUFFER_END, +}; + +uint32_t gen8_batch[] = { + (XY_SRC_COPY_BLT_CMD | 8 | + XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB), + (3 << 24 | /* 32 bits */ + 0xcc << 16 | /* copy ROP */ + 4096), + 0 << 16 | 0, /* dst x1, y1 */ + 1 << 16 | 2, + 0, /* dst relocation */ + 0, /* FIXME */ + 0 << 16 | 0, /* src x1, y1 */ + 4096, + 0, /* src relocation */ + 0, /* FIXME */ + MI_BATCH_BUFFER_END, +}; + +uint32_t *batch = gen6_batch; +uint32_t batch_size = sizeof(gen6_batch); + +igt_simple_main +{ + const uint32_t hang[] = {-1, -1, -1, -1}; + const uint32_t end[] = {MI_BATCH_BUFFER_END, 0}; + uint64_t aper_size; + uint32_t noop; + uint32_t *handles; + int fd, i, count; + + fd = drm_open_any(); + noop = intel_get_drm_devid(fd); + + use_blt = 0; + if (intel_gen(noop) >= 6) + use_blt = I915_EXEC_BLT; + + if (intel_gen(noop) >= 8) { + batch = gen8_batch; + batch_size += 2 * 4; + } + + aper_size = gem_mappable_aperture_size(); + igt_skip_on_f(intel_get_total_ram_mb() < aper_size / (1024*1024) * 2, + "not enough mem to run test\n"); + + count = aper_size / 4096 * 2; + if (igt_run_in_simulation()) + count = 10; + + handles = malloc (count * sizeof(uint32_t)); + igt_assert(handles); + + noop = gem_create(fd, 4096); + gem_write(fd, noop, 0, end, sizeof(end)); + + /* fill the entire gart with batches and run them */ + for (i = 0; i < count; i++) { + uint32_t bad; + + handles[i] = gem_create(fd, 4096); + gem_write(fd, handles[i], 0, batch, batch_size); + + bad = gem_create(fd, 4096); + gem_write(fd, bad, 0, hang, sizeof(hang)); + + /* launch the newly created batch */ + copy(fd, handles[i], noop, bad); + exec(fd, bad); + gem_close(fd, bad); + + igt_progress("gem_cpu_reloc: ", i, 2*count); + } + + /* And again in reverse to try and catch the relocation code out */ + for (i = 0; i < count; i++) { + uint32_t bad; + + bad = gem_create(fd, 4096); + gem_write(fd, bad, 0, hang, sizeof(hang)); + + /* launch the newly created batch */ + copy(fd, handles[count-i-1], noop, bad); + exec(fd, bad); + gem_close(fd, bad); + + igt_progress("gem_cpu_reloc: ", count+i, 3*count); + } + + /* Third time lucky? */ + for (i = 0; i < count; i++) { + uint32_t bad; + + bad = gem_create(fd, 4096); + gem_write(fd, bad, 0, hang, sizeof(hang)); + + /* launch the newly created batch */ + gem_set_domain(fd, handles[i], + I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); + copy(fd, handles[i], noop, bad); + exec(fd, bad); + gem_close(fd, bad); + + igt_progress("gem_cpu_reloc: ", 2*count+i, 3*count); + } + + igt_info("Test suceeded, cleanup up - this might take a while.\n"); + close(fd); +} diff --git a/tests/gem_cs_prefetch.c b/tests/gem_cs_prefetch.c index 4fb2fc4e..2fd83c9e 100644 --- a/tests/gem_cs_prefetch.c +++ b/tests/gem_cs_prefetch.c @@ -31,22 +31,28 @@ * Historically the batch prefetcher doesn't check whether it's crossing page * boundaries and likes to throw up when it gets a pagefault in return for his * over-eager behaviour. Check for this. + * + * This test for a bug where we've failed to plug a scratch pte entry into the + * very last gtt pte. */ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> -#include "drm.h" -#include "i915_drm.h" + +#include <drm.h> + +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "intel_chipset.h" +#include "igt_aux.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; @@ -82,10 +88,10 @@ static void exec(int fd, uint32_t handle) DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); gem_sync(fd, handle); - assert(ret == 0); + igt_assert(ret == 0); } -int main(int argc, char **argv) +igt_simple_main { uint32_t batch_end[4] = {MI_BATCH_BUFFER_END, 0, 0, 0}; int fd, i, ret; @@ -93,57 +99,53 @@ int main(int argc, char **argv) int count; drm_intel_bo *sample_batch_bo; + igt_skip_on_simulation(); + fd = drm_open_any(); bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - if (!bufmgr) { - fprintf(stderr, "failed to init libdrm\n"); - exit(-1); - } + igt_assert(bufmgr); drm_intel_bufmgr_gem_enable_reuse(bufmgr); aper_size = gem_aperture_size(fd); /* presume a big per-bo overhead */ - if (intel_get_total_ram_mb() < (aper_size / (1024*1024)) * 3 / 2) { - fprintf(stderr, "not enough mem to run test\n"); - return 77; - } + igt_skip_on_f(intel_get_total_ram_mb() < (aper_size / (1024*1024)) * 3 / 2, + "not enough mem to run test\n"); count = aper_size / 4096; batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); - assert(batch); + igt_assert(batch); sample_batch_bo = drm_intel_bo_alloc(bufmgr, "", 4096, 4096); - assert(sample_batch_bo); + igt_assert(sample_batch_bo); ret = drm_intel_bo_subdata(sample_batch_bo, 4096-sizeof(batch_end), sizeof(batch_end), batch_end); - assert(ret == 0); + igt_assert(ret == 0); /* fill the entire gart with batches and run them */ for (i = 0; i < count; i++) { drm_intel_bo *batch_bo; batch_bo = drm_intel_bo_alloc(bufmgr, "", 4096, 4096); - assert(batch_bo); + igt_assert(batch_bo); /* copy the sample batch with the gpu to the new one, so that we * also test the unmappable part of the gtt. */ - BEGIN_BATCH(8); - OUT_BATCH(XY_SRC_COPY_BLT_CMD | - XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); + BLIT_COPY_BATCH_START(batch->devid, 0); OUT_BATCH((3 << 24) | /* 32 bits */ (0xcc << 16) | /* copy ROP */ 4096); OUT_BATCH(0); /* dst y1,x1 */ OUT_BATCH((1 << 16) | 1024); OUT_RELOC(batch_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(batch->devid); OUT_BATCH((0 << 16) | 0); /* src x1, y1 */ OUT_BATCH(4096); OUT_RELOC(sample_batch_bo, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(batch->devid); ADVANCE_BATCH(); intel_batchbuffer_flush(batch); @@ -157,13 +159,11 @@ int main(int argc, char **argv) // leak buffers //drm_intel_bo_unreference(batch_bo); - drmtest_progress("gem_cs_prefetch: ", i, count); + igt_progress("gem_cs_prefetch: ", i, count); } - fprintf(stderr, "Test suceeded, cleanup up - this might take a while.\n"); + igt_info("Test suceeded, cleanup up - this might take a while.\n"); drm_intel_bufmgr_destroy(bufmgr); close(fd); - - return 0; } diff --git a/tests/gem_cs_tlb.c b/tests/gem_cs_tlb.c new file mode 100644 index 00000000..b1c50584 --- /dev/null +++ b/tests/gem_cs_tlb.c @@ -0,0 +1,179 @@ +/* + * Copyright © 2011,2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Chris Wilson <chris@chris-wilson.co.uk> + * Daniel Vetter <daniel.vetter@ffwll.ch> + * + */ + +/* + * Testcase: Check whether we correctly invalidate the cs tlb + * + * Motivated by a strange bug on launchpad where *acth != ipehr, on snb notably + * where everything should be coherent by default. + * + * https://bugs.launchpad.net/ubuntu/+source/xserver-xorg-video-intel/+bug/1063252 + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/time.h> + +#include <drm.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_io.h" +#include "igt_aux.h" + +#define LOCAL_I915_EXEC_VEBOX (4<<0) +#define BATCH_SIZE (1024*1024) + +static int exec(int fd, uint32_t handle, int split, + uint64_t *gtt_ofs, unsigned ring_id) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 gem_exec[1]; + int ret = 0; + + gem_exec[0].handle = handle; + gem_exec[0].relocation_count = 0; + gem_exec[0].relocs_ptr = 0; + gem_exec[0].alignment = 0; + gem_exec[0].offset = 0x00100000; + gem_exec[0].flags = 0; + gem_exec[0].rsvd1 = 0; + gem_exec[0].rsvd2 = 0; + + execbuf.buffers_ptr = (uintptr_t)gem_exec; + execbuf.buffer_count = 1; + execbuf.batch_start_offset = 0; + execbuf.batch_len = 8*(split+1); + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = ring_id; + i915_execbuffer2_set_context_id(execbuf, 0); + execbuf.rsvd2 = 0; + + ret = drmIoctl(fd, + DRM_IOCTL_I915_GEM_EXECBUFFER2, + &execbuf); + + *gtt_ofs = gem_exec[0].offset; + + return ret; +} + +static void run_on_ring(int fd, unsigned ring_id, const char *ring_name) +{ + uint32_t handle, handle_new; + uint64_t gtt_offset, gtt_offset_new; + uint32_t *batch_ptr, *batch_ptr_old; + unsigned split; + char buf[100]; + int i; + + gem_require_ring(fd, ring_id); + + sprintf(buf, "testing %s cs tlb coherency: ", ring_name); + + /* Shut up gcc, too stupid. */ + batch_ptr_old = NULL; + handle = 0; + gtt_offset = 0; + + for (split = 0; split < BATCH_SIZE/8 - 1; split += 2) { + igt_progress(buf, split, BATCH_SIZE/8 - 1); + + handle_new = gem_create(fd, BATCH_SIZE); + batch_ptr = gem_mmap__cpu(fd, handle_new, BATCH_SIZE, + PROT_READ | PROT_WRITE); + batch_ptr[split*2] = MI_BATCH_BUFFER_END; + + for (i = split*2 + 2; i < BATCH_SIZE/8; i++) + batch_ptr[i] = 0xffffffff; + + if (split > 0) { + gem_sync(fd, handle); + gem_close(fd, handle); + } + + igt_assert(exec(fd, handle_new, split, >t_offset_new, 0) == 0); + + if (split > 0) { + /* Check that we've managed to collide in the tlb. */ + igt_assert(gtt_offset == gtt_offset_new); + + /* We hang onto the storage of the old batch by keeping + * the cpu mmap around. */ + munmap(batch_ptr_old, BATCH_SIZE); + } + + handle = handle_new; + gtt_offset = gtt_offset_new; + batch_ptr_old = batch_ptr; + } + +} + +int fd; + +igt_main +{ + + igt_skip_on_simulation(); + + igt_fixture { + fd = drm_open_any(); + + /* This test is very sensitive to residual gtt_mm noise from previous + * tests. Try to quiet thing down first. */ + gem_quiescent_gpu(fd); + sleep(5); /* needs more serious ducttape */ + } + + igt_subtest("render") + run_on_ring(fd, I915_EXEC_RENDER, "render"); + + igt_subtest("bsd") + run_on_ring(fd, I915_EXEC_BSD, "bsd"); + + igt_subtest("blt") + run_on_ring(fd, I915_EXEC_BLT, "blt"); + + igt_subtest("vebox") + run_on_ring(fd, LOCAL_I915_EXEC_VEBOX, "vebox"); + + igt_fixture + close(fd); +} diff --git a/tests/gem_ctx_bad_destroy.c b/tests/gem_ctx_bad_destroy.c index 02d24eb3..77091314 100644 --- a/tests/gem_ctx_bad_destroy.c +++ b/tests/gem_ctx_bad_destroy.c @@ -31,79 +31,48 @@ #include <stdio.h> #include <string.h> -#include "i915_drm.h" -#include "drmtest.h" +#include <errno.h> -struct local_drm_i915_context_create { - __u32 ctx_id; - __u32 pad; -}; +#include "ioctl_wrappers.h" +#include "drmtest.h" struct local_drm_i915_context_destroy { __u32 ctx_id; __u32 pad; }; -#define CONTEXT_CREATE_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x2d, struct local_drm_i915_context_create) #define CONTEXT_DESTROY_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x2e, struct local_drm_i915_context_destroy) -static uint32_t context_create(int fd) -{ - struct local_drm_i915_context_create create; - int ret; - - ret = drmIoctl(fd, CONTEXT_CREATE_IOCTL, &create); - if (ret == -1 && (errno == ENODEV || errno == EINVAL)) - exit(77); - else if (ret) - abort(); - - return create.ctx_id; -} - -static void handle_bad(int ret, int lerrno, int expected, const char *desc) -{ - if (ret != 0 && lerrno != expected) { - fprintf(stderr, "%s - errno was %d, but should have been %d\n", - desc, lerrno, expected); - exit(EXIT_FAILURE); - } else if (ret == 0) { - fprintf(stderr, "%s - Command succeeded, but should have failed\n", - desc); - exit(EXIT_FAILURE); - } -} - -int main(int argc, char *argv[]) +igt_simple_main { struct local_drm_i915_context_destroy destroy; uint32_t ctx_id; int ret, fd; - fd = drm_open_any(); + igt_skip_on_simulation(); + + fd = drm_open_any_render(); - ctx_id = context_create(fd); + ctx_id = gem_context_create(fd); destroy.ctx_id = ctx_id; /* Make sure a proper destroy works first */ ret = drmIoctl(fd, CONTEXT_DESTROY_IOCTL, &destroy); - assert(ret == 0); + igt_assert(ret == 0); /* try double destroy */ ret = drmIoctl(fd, CONTEXT_DESTROY_IOCTL, &destroy); - handle_bad(ret, errno, ENOENT, "double destroy"); + igt_assert(ret != 0 && errno == ENOENT); /* destroy something random */ destroy.ctx_id = 2; ret = drmIoctl(fd, CONTEXT_DESTROY_IOCTL, &destroy); - handle_bad(ret, errno, ENOENT, "random destroy"); + igt_assert(ret != 0 && errno == ENOENT); /* Try to destroy the default context */ destroy.ctx_id = 0; ret = drmIoctl(fd, CONTEXT_DESTROY_IOCTL, &destroy); - handle_bad(ret, errno, ENOENT, "default destroy"); + igt_assert(ret != 0 && errno == ENOENT); close(fd); - - exit(EXIT_SUCCESS); } diff --git a/tests/gem_ctx_bad_exec.c b/tests/gem_ctx_bad_exec.c index 8a57fd41..f0bb0fc9 100644 --- a/tests/gem_ctx_bad_exec.c +++ b/tests/gem_ctx_bad_exec.c @@ -35,40 +35,16 @@ #include <stdint.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/ioctl.h> -#include <sys/mman.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" -struct local_drm_i915_gem_context_create { - __u32 ctx_id; - __u32 pad; -}; - -#define CONTEXT_CREATE_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x2d, struct local_drm_i915_gem_context_create) - -static uint32_t context_create(int fd) -{ - struct local_drm_i915_gem_context_create create; - int ret; - - ret = drmIoctl(fd, CONTEXT_CREATE_IOCTL, &create); - if (ret == -1 && (errno == ENODEV || errno == EINVAL)) { - exit(77); - } else if (ret) { - abort(); - } - - return create.ctx_id; -} - /* Copied from gem_exec_nop.c */ static int exec(int fd, uint32_t handle, int ring, int ctx_id) { @@ -104,22 +80,34 @@ static int exec(int fd, uint32_t handle, int ring, int ctx_id) return ret; } -#define MI_BATCH_BUFFER_END (0xA<<23) -int main(int argc, char *argv[]) +uint32_t handle; +uint32_t batch[2] = {MI_BATCH_BUFFER_END}; +uint32_t ctx_id; +int fd; + +igt_main { - uint32_t handle; - uint32_t batch[2] = {MI_BATCH_BUFFER_END}; - uint32_t ctx_id; - int fd; - fd = drm_open_any(); + igt_skip_on_simulation(); - ctx_id = context_create(fd); + igt_fixture { + fd = drm_open_any_render(); - handle = gem_create(fd, 4096); - gem_write(fd, handle, 0, batch, sizeof(batch)); - assert(exec(fd, handle, I915_EXEC_RENDER, ctx_id) == 0); - assert(exec(fd, handle, I915_EXEC_BSD, ctx_id) != 0); - assert(exec(fd, handle, I915_EXEC_BLT, ctx_id) != 0); + ctx_id = gem_context_create(fd); + + handle = gem_create(fd, 4096); + gem_write(fd, handle, 0, batch, sizeof(batch)); + } - exit(EXIT_SUCCESS); + igt_subtest("render") + igt_assert(exec(fd, handle, I915_EXEC_RENDER, ctx_id) == 0); + igt_subtest("bsd") + igt_assert(exec(fd, handle, I915_EXEC_BSD, ctx_id) != 0); + igt_subtest("blt") + igt_assert(exec(fd, handle, I915_EXEC_BLT, ctx_id) != 0); +#ifdef I915_EXEC_VEBOX + igt_fixture + igt_require(gem_has_vebox(fd)); + igt_subtest("vebox") + igt_assert(exec(fd, handle, I915_EXEC_VEBOX, ctx_id) != 0); +#endif } diff --git a/tests/gem_ctx_basic.c b/tests/gem_ctx_basic.c index 632651ae..3e9b6880 100644 --- a/tests/gem_ctx_basic.c +++ b/tests/gem_ctx_basic.c @@ -30,7 +30,23 @@ */ #include <pthread.h> -#include "rendercopy.h" +#include <stdlib.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <getopt.h> +#include "drm.h" +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_io.h" +#include "intel_chipset.h" /* options */ int num_contexts = 10; @@ -40,17 +56,16 @@ int iter = 10000; /* globals */ pthread_t *threads; -int *returns; int devid; int fd; static void init_buffer(drm_intel_bufmgr *bufmgr, - struct scratch_buf *buf, + struct igt_buf *buf, uint32_t size) { buf->bo = drm_intel_bo_alloc(bufmgr, "", size, 4096); buf->size = size; - assert(buf->bo); + igt_assert(buf->bo); buf->tiling = I915_TILING_NONE; buf->stride = 4096; } @@ -58,46 +73,42 @@ static void init_buffer(drm_intel_bufmgr *bufmgr, static void *work(void *arg) { struct intel_batchbuffer *batch; + igt_render_copyfunc_t rendercopy = igt_get_render_copyfunc(devid); drm_intel_context *context; drm_intel_bufmgr *bufmgr; - int thread_id = *(int *)arg; int td_fd; int i; if (multiple_fds) - td_fd = fd = drm_open_any(); + td_fd = fd = drm_open_any_render(); else td_fd = fd; - assert(td_fd >= 0); + igt_assert(td_fd >= 0); bufmgr = drm_intel_bufmgr_gem_init(td_fd, 4096); batch = intel_batchbuffer_alloc(bufmgr, devid); context = drm_intel_gem_context_create(bufmgr); - - if (!context) { - returns[thread_id] = 77; - goto out; - } + igt_require(context); for (i = 0; i < iter; i++) { - struct scratch_buf src, dst; + struct igt_buf src, dst; init_buffer(bufmgr, &src, 4096); init_buffer(bufmgr, &dst, 4096); if (uncontexted) { - gen6_render_copyfunc(batch, &src, 0, 0, 0, 0, &dst, 0, 0); + igt_assert(rendercopy); + rendercopy(batch, NULL, &src, 0, 0, 0, 0, &dst, 0, 0); } else { int ret; ret = drm_intel_bo_subdata(batch->bo, 0, 4096, batch->buffer); - assert(ret == 0); + igt_assert(ret == 0); intel_batchbuffer_flush_with_context(batch, context); } } -out: drm_intel_gem_context_destroy(context); intel_batchbuffer_free(batch); drm_intel_bufmgr_destroy(bufmgr); @@ -105,7 +116,7 @@ out: if (multiple_fds) close(td_fd); - pthread_exit(&returns[thread_id]); + pthread_exit(NULL); } static void parse(int argc, char *argv[]) @@ -128,7 +139,7 @@ static void parse(int argc, char *argv[]) case 'h': case '?': default: - exit(EXIT_SUCCESS); + igt_success(); break; } } @@ -138,29 +149,30 @@ int main(int argc, char *argv[]) { int i; - fd = drm_open_any(); + igt_simple_init(); + + fd = drm_open_any_render(); devid = intel_get_drm_devid(fd); + if (igt_run_in_simulation()) { + num_contexts = 2; + iter = 4; + } + parse(argc, argv); threads = calloc(num_contexts, sizeof(*threads)); - returns = calloc(num_contexts, sizeof(*returns)); for (i = 0; i < num_contexts; i++) pthread_create(&threads[i], NULL, work, &i); for (i = 0; i < num_contexts; i++) { - int thread_status, ret; void *retval; - ret = pthread_join(threads[i], &retval); - thread_status = *(int *)retval; - if (!ret && thread_status) - exit(thread_status); + igt_assert(pthread_join(threads[i], &retval) == 0); } - free(returns); free(threads); close(fd); - exit(EXIT_SUCCESS); + return 0; } diff --git a/tests/gem_ctx_create.c b/tests/gem_ctx_create.c index def76d34..522e7b1c 100644 --- a/tests/gem_ctx_create.c +++ b/tests/gem_ctx_create.c @@ -27,7 +27,9 @@ #include <stdio.h> #include <string.h> -#include "i915_drm.h" +#include <errno.h> + +#include "ioctl_wrappers.h" #include "drmtest.h" struct local_drm_i915_gem_context_create { @@ -37,28 +39,22 @@ struct local_drm_i915_gem_context_create { #define CONTEXT_CREATE_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x2d, struct local_drm_i915_gem_context_create) -int main(int argc, char *argv[]) +igt_simple_main { int ret, fd; struct local_drm_i915_gem_context_create create; + igt_skip_on_simulation(); + create.ctx_id = rand(); create.pad = rand(); - fd = drm_open_any(); + fd = drm_open_any_render(); ret = drmIoctl(fd, CONTEXT_CREATE_IOCTL, &create); - if (ret != 0 && (errno == ENODEV || errno == EINVAL)) { - fprintf(stderr, "Kernel is too old, or contexts not supported: %s\n", - strerror(errno)); - exit(77); - } else if (ret != 0) { - fprintf(stderr, "%s\n", strerror(errno)); - exit(EXIT_FAILURE); - } - assert(create.ctx_id != 0); + igt_skip_on(ret != 0 && (errno == ENODEV || errno == EINVAL)); + igt_assert(ret == 0); + igt_assert(create.ctx_id != 0); close(fd); - - exit(EXIT_SUCCESS); } diff --git a/tests/gem_ctx_exec.c b/tests/gem_ctx_exec.c index 423f1eec..da49a2fb 100644 --- a/tests/gem_ctx_exec.c +++ b/tests/gem_ctx_exec.c @@ -34,50 +34,32 @@ #include <stdint.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/ioctl.h> -#include <sys/mman.h> #include <sys/time.h> -#include "drm.h" -#include "i915_drm.h" -#include "drmtest.h" -struct local_drm_i915_gem_context_create { - __u32 ctx_id; - __u32 pad; -}; +#include <drm.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "igt_aux.h" struct local_drm_i915_gem_context_destroy { __u32 ctx_id; __u32 pad; }; -#define CONTEXT_CREATE_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x2d, struct local_drm_i915_gem_context_create) -#define CONTEXT_DESTROY_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x23, struct local_drm_i915_gem_context_destroy) - -static uint32_t context_create(int fd) -{ - struct local_drm_i915_gem_context_create create; - int ret; - - ret = drmIoctl(fd, CONTEXT_CREATE_IOCTL, &create); - if (ret == -1 && (errno == ENODEV || errno == EINVAL)) - exit(77); - else if (ret) - abort(); - - return create.ctx_id; -} +#define CONTEXT_DESTROY_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x2e, struct local_drm_i915_gem_context_destroy) static void context_destroy(int fd, uint32_t ctx_id) { struct local_drm_i915_gem_context_destroy destroy; destroy.ctx_id = ctx_id; do_ioctl(fd, CONTEXT_DESTROY_IOCTL, &destroy); +#include "igt_aux.h" } /* Copied from gem_exec_nop.c */ @@ -115,25 +97,106 @@ static int exec(int fd, uint32_t handle, int ring, int ctx_id) return ret; } -#define MI_BATCH_BUFFER_END (0xA<<23) -int main(int argc, char *argv[]) +static void big_exec(int fd, uint32_t handle, int ring) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 *gem_exec; + uint32_t ctx_id1, ctx_id2; + int num_buffers = gem_available_aperture_size(fd) / 4096; + int i; + + /* Make sure we only fill half of RAM with gem objects. */ + igt_require(intel_get_total_ram_mb() * 1024 / 2 > num_buffers * 4); + + gem_exec = calloc(num_buffers + 1, sizeof(*gem_exec)); + igt_assert(gem_exec); + memset(gem_exec, 0, (num_buffers + 1) * sizeof(*gem_exec)); + + + ctx_id1 = gem_context_create(fd); + ctx_id2 = gem_context_create(fd); + + gem_exec[0].handle = handle; + + + execbuf.buffers_ptr = (uintptr_t)gem_exec; + execbuf.buffer_count = num_buffers + 1; + execbuf.batch_start_offset = 0; + execbuf.batch_len = 8; + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = ring; + execbuf.rsvd2 = 0; + + execbuf.buffer_count = 1; + i915_execbuffer2_set_context_id(execbuf, ctx_id1); + igt_assert(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, + &execbuf) == 0); + + for (i = 0; i < num_buffers; i++) { + uint32_t tmp_handle = gem_create(fd, 4096); + + gem_exec[i].handle = tmp_handle; + } + gem_exec[i].handle = handle; + execbuf.buffer_count = i + 1; + + /* figure out how many buffers we can exactly fit */ + while (drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, + &execbuf) != 0) { + i--; + gem_close(fd, gem_exec[i].handle); + gem_exec[i].handle = handle; + execbuf.buffer_count--; + igt_info("trying buffer count %i\n", i - 1); + } + + igt_info("reduced buffer count to %i from %i\n", + i - 1, num_buffers); + + /* double check that it works */ + igt_assert(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, + &execbuf) == 0); + + i915_execbuffer2_set_context_id(execbuf, ctx_id2); + igt_assert(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, + &execbuf) == 0); + gem_sync(fd, handle); +} + +uint32_t handle; +uint32_t batch[2] = {0, MI_BATCH_BUFFER_END}; +uint32_t ctx_id; +int fd; + +igt_main { - uint32_t handle; - uint32_t batch[2] = {0, MI_BATCH_BUFFER_END}; - uint32_t ctx_id; - int fd; - fd = drm_open_any(); + igt_skip_on_simulation(); + igt_fixture { + fd = drm_open_any_render(); + + handle = gem_create(fd, 4096); + + /* check that we can create contexts. */ + ctx_id = gem_context_create(fd); + context_destroy(fd, ctx_id); + gem_write(fd, handle, 0, batch, sizeof(batch)); + } - ctx_id = context_create(fd); - handle = gem_create(fd, 4096); + igt_subtest("basic") { + ctx_id = gem_context_create(fd); + igt_assert(exec(fd, handle, I915_EXEC_RENDER, ctx_id) == 0); + context_destroy(fd, ctx_id); - gem_write(fd, handle, 0, batch, sizeof(batch)); - assert(exec(fd, handle, I915_EXEC_RENDER, ctx_id) == 0); - context_destroy(fd, ctx_id); + ctx_id = gem_context_create(fd); + igt_assert(exec(fd, handle, I915_EXEC_RENDER, ctx_id) == 0); + context_destroy(fd, ctx_id); - ctx_id = context_create(fd); - assert(exec(fd, handle, I915_EXEC_RENDER, ctx_id) == 0); - context_destroy(fd, ctx_id); + igt_assert(exec(fd, handle, I915_EXEC_RENDER, ctx_id) < 0); + } - exit(EXIT_SUCCESS); + igt_subtest("eviction") + big_exec(fd, handle, I915_EXEC_RENDER); } diff --git a/tests/gem_double_irq_loop.c b/tests/gem_double_irq_loop.c index f2f8b1a8..ee9846c3 100644 --- a/tests/gem_double_irq_loop.c +++ b/tests/gem_double_irq_loop.c @@ -28,19 +28,19 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" #include "i830_reg.h" +#include "intel_chipset.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; @@ -62,19 +62,18 @@ dummy_reloc_loop(void) int i; for (i = 0; i < 0x800; i++) { - BEGIN_BATCH(8); - OUT_BATCH(XY_SRC_COPY_BLT_CMD | - XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); + BLIT_COPY_BATCH_START(batch->devid, 0); OUT_BATCH((3 << 24) | /* 32 bits */ (0xcc << 16) | /* copy ROP */ 4*4096); OUT_BATCH(2048 << 16 | 0); OUT_BATCH((4096) << 16 | (2048)); OUT_RELOC_FENCED(blt_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(batch->devid); OUT_BATCH(0 << 16 | 0); OUT_BATCH(4*4096); OUT_RELOC_FENCED(blt_bo, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(batch->devid); ADVANCE_BATCH(); intel_batchbuffer_flush(batch); @@ -93,47 +92,30 @@ dummy_reloc_loop(void) } } -int main(int argc, char **argv) +igt_simple_main { int fd; int devid; - if (argc != 1) { - fprintf(stderr, "usage: %s\n", argv[0]); - exit(-1); - } + igt_skip_on_simulation(); fd = drm_open_any(); devid = intel_get_drm_devid(fd); - if (!HAS_BLT_RING(devid)) { - fprintf(stderr, "not (yet) implemented for pre-snb\n"); - return 77; - } + igt_require_f(HAS_BLT_RING(devid), + "not (yet) implemented for pre-snb\n"); bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - if (!bufmgr) { - fprintf(stderr, "failed to init libdrm\n"); - exit(-1); - } + igt_assert(bufmgr); drm_intel_bufmgr_gem_enable_reuse(bufmgr); batch = intel_batchbuffer_alloc(bufmgr, devid); - if (!batch) { - fprintf(stderr, "failed to create batch buffer\n"); - exit(-1); - } + igt_assert(batch); target_buffer = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096); - if (!target_buffer) { - fprintf(stderr, "failed to alloc target buffer\n"); - exit(-1); - } + igt_assert(target_buffer); blt_bo = drm_intel_bo_alloc(bufmgr, "target bo", 4*4096*4096, 4096); - if (!blt_bo) { - fprintf(stderr, "failed to alloc blt buffer\n"); - exit(-1); - } + igt_assert(blt_bo); dummy_reloc_loop(); @@ -142,6 +124,4 @@ int main(int argc, char **argv) drm_intel_bufmgr_destroy(bufmgr); close(fd); - - return 0; } diff --git a/tests/gem_dummy_reloc_loop.c b/tests/gem_dummy_reloc_loop.c index 82d8f77e..4fe07860 100644 --- a/tests/gem_dummy_reloc_loop.c +++ b/tests/gem_dummy_reloc_loop.c @@ -28,24 +28,33 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" #include "i830_reg.h" +#include "intel_chipset.h" + +#define LOCAL_I915_EXEC_VEBOX (4<<0) static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; static drm_intel_bo *target_buffer; +#define NUM_FD 50 + +static int mfd[NUM_FD]; +static drm_intel_bufmgr *mbufmgr[NUM_FD]; +static struct intel_batchbuffer *mbatch[NUM_FD]; +static drm_intel_bo *mbuffer[NUM_FD]; + /* * Testcase: Basic check of ring<->cpu sync using a dummy reloc * @@ -88,14 +97,14 @@ dummy_reloc_loop(int ring) } static void -dummy_reloc_loop_random_ring(void) +dummy_reloc_loop_random_ring(int num_rings) { int i; srandom(0xdeadbeef); for (i = 0; i < 0x100000; i++) { - int ring = random() % 3 + 1; + int ring = random() % num_rings + 1; if (ring == I915_EXEC_RENDER) { BEGIN_BATCH(4); @@ -122,73 +131,173 @@ dummy_reloc_loop_random_ring(void) } } -int main(int argc, char **argv) +static void +dummy_reloc_loop_random_ring_multi_fd(int num_rings) { - int fd; - int devid; + int i; + struct intel_batchbuffer *saved_batch; - if (argc != 1) { - fprintf(stderr, "usage: %s\n", argv[0]); - exit(-1); - } + saved_batch = batch; - fd = drm_open_any(); - devid = intel_get_drm_devid(fd); - if (!HAS_BLT_RING(devid)) { - fprintf(stderr, "not (yet) implemented for pre-snb\n"); - return 77; - } + srandom(0xdeadbeef); - bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - if (!bufmgr) { - fprintf(stderr, "failed to init libdrm\n"); - exit(-1); - } - drm_intel_bufmgr_gem_enable_reuse(bufmgr); + for (i = 0; i < 0x100000; i++) { + int mindex; + int ring = random() % num_rings + 1; - batch = intel_batchbuffer_alloc(bufmgr, devid); - if (!batch) { - fprintf(stderr, "failed to create batch buffer\n"); - exit(-1); - } + mindex = random() % NUM_FD; + batch = mbatch[mindex]; - target_buffer = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096); - if (!target_buffer) { - fprintf(stderr, "failed to alloc target buffer\n"); - exit(-1); + if (ring == I915_EXEC_RENDER) { + BEGIN_BATCH(4); + OUT_BATCH(MI_COND_BATCH_BUFFER_END | MI_DO_COMPARE); + OUT_BATCH(0xffffffff); /* compare dword */ + OUT_RELOC(mbuffer[mindex], I915_GEM_DOMAIN_RENDER, + I915_GEM_DOMAIN_RENDER, 0); + OUT_BATCH(MI_NOOP); + ADVANCE_BATCH(); + } else { + BEGIN_BATCH(4); + OUT_BATCH(MI_FLUSH_DW | 1); + OUT_BATCH(0); /* reserved */ + OUT_RELOC(mbuffer[mindex], I915_GEM_DOMAIN_RENDER, + I915_GEM_DOMAIN_RENDER, 0); + OUT_BATCH(MI_NOOP | (1<<22) | (0xf)); + ADVANCE_BATCH(); + } + intel_batchbuffer_flush_on_ring(batch, ring); + + drm_intel_bo_map(target_buffer, 0); + // map to force waiting on rendering + drm_intel_bo_unmap(target_buffer); } - fprintf(stderr, "running dummy loop on render\n"); - dummy_reloc_loop(I915_EXEC_RENDER); - fprintf(stderr, "dummy loop run on render completed\n"); + batch = saved_batch; +} - if (!HAS_BSD_RING(devid)) - goto skip; +int fd; +int devid; +int num_rings; - sleep(2); - fprintf(stderr, "running dummy loop on bsd\n"); - dummy_reloc_loop(I915_EXEC_BSD); - fprintf(stderr, "dummy loop run on bsd completed\n"); +igt_main +{ + igt_skip_on_simulation(); - if (!HAS_BLT_RING(devid)) - goto skip; + igt_fixture { + int i; + fd = drm_open_any(); + devid = intel_get_drm_devid(fd); + num_rings = gem_get_num_rings(fd); + /* Not yet implemented on pre-snb. */ + igt_require(HAS_BLT_RING(devid)); - sleep(2); - fprintf(stderr, "running dummy loop on blt\n"); - dummy_reloc_loop(I915_EXEC_BLT); - fprintf(stderr, "dummy loop run on blt completed\n"); + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + igt_assert(bufmgr); + drm_intel_bufmgr_gem_enable_reuse(bufmgr); - sleep(2); - fprintf(stderr, "running dummy loop on random rings\n"); - dummy_reloc_loop_random_ring(); - fprintf(stderr, "dummy loop run on random rings completed\n"); + batch = intel_batchbuffer_alloc(bufmgr, devid); + igt_assert(batch); -skip: - drm_intel_bo_unreference(target_buffer); - intel_batchbuffer_free(batch); - drm_intel_bufmgr_destroy(bufmgr); + target_buffer = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096); + igt_assert(target_buffer); - close(fd); + /* Create multi drm_fd and map one gem object to multi gem_contexts */ + { + unsigned int target_flink; + char buffer_name[32]; + igt_assert(dri_bo_flink(target_buffer, &target_flink) == 0); - return 0; + for (i = 0; i < NUM_FD; i++) { + sprintf(buffer_name, "Target buffer %d\n", i); + mfd[i] = drm_open_any(); + mbufmgr[i] = drm_intel_bufmgr_gem_init(mfd[i], 4096); + igt_assert_f(mbufmgr[i], + "fail to initialize buf manager " + "for drm_fd %d\n", + mfd[i]); + drm_intel_bufmgr_gem_enable_reuse(mbufmgr[i]); + mbatch[i] = intel_batchbuffer_alloc(mbufmgr[i], devid); + igt_assert_f(mbatch[i], + "fail to create batchbuffer " + "for drm_fd %d\n", + mfd[i]); + mbuffer[i] = intel_bo_gem_create_from_name( + mbufmgr[i], + buffer_name, + target_flink); + igt_assert_f(mbuffer[i], + "fail to create gem bo from global " + "gem_handle %d for drm_fd %d\n", + target_flink, mfd[i]); + } + } + } + + igt_subtest("render") { + igt_info("running dummy loop on render\n"); + dummy_reloc_loop(I915_EXEC_RENDER); + igt_info("dummy loop run on render completed\n"); + } + + igt_subtest("bsd") { + gem_require_ring(fd, I915_EXEC_BSD); + sleep(2); + igt_info("running dummy loop on bsd\n"); + dummy_reloc_loop(I915_EXEC_BSD); + igt_info("dummy loop run on bsd completed\n"); + } + + igt_subtest("blt") { + gem_require_ring(fd, I915_EXEC_BLT); + sleep(2); + igt_info("running dummy loop on blt\n"); + dummy_reloc_loop(I915_EXEC_BLT); + igt_info("dummy loop run on blt completed\n"); + } + +#ifdef I915_EXEC_VEBOX + igt_subtest("vebox") { + gem_require_ring(fd, I915_EXEC_VEBOX); + sleep(2); + igt_info("running dummy loop on vebox\n"); + dummy_reloc_loop(LOCAL_I915_EXEC_VEBOX); + igt_info("dummy loop run on vebox completed\n"); + } +#endif + + igt_subtest("mixed") { + if (num_rings > 1) { + sleep(2); + igt_info("running dummy loop on random rings\n"); + dummy_reloc_loop_random_ring(num_rings); + igt_info("dummy loop run on random rings completed\n"); + } + } + igt_subtest("mixed_multi_fd") { + if (num_rings > 1) { + sleep(2); + igt_info("running dummy loop on random rings based on " + "multi drm_fd\n"); + dummy_reloc_loop_random_ring_multi_fd(num_rings); + igt_info("dummy loop run on random rings based on " + "multi drm_fd completed\n"); + } + } + igt_fixture { + int i; + /* Free the buffer/batchbuffer/buffer mgr for multi-fd */ + { + for (i = 0; i < NUM_FD; i++) { + dri_bo_unreference(mbuffer[i]); + intel_batchbuffer_free(mbatch[i]); + drm_intel_bufmgr_destroy(mbufmgr[i]); + close(mfd[i]); + } + } + drm_intel_bo_unreference(target_buffer); + intel_batchbuffer_free(batch); + drm_intel_bufmgr_destroy(bufmgr); + + close(fd); + } } diff --git a/tests/gem_evict_alignment.c b/tests/gem_evict_alignment.c new file mode 100644 index 00000000..e814f36c --- /dev/null +++ b/tests/gem_evict_alignment.c @@ -0,0 +1,228 @@ +/* + * Copyright © 2011,2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Chris Wilson <chris@chris-wilson.co.uk> + * Daniel Vetter <daniel.vetter@ffwll.ch> + * + */ + +/* + * Testcase: run a couple of big batches to force the unbind on misalignment code. + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/time.h> + +#include <drm.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_chipset.h" +#include "igt_aux.h" + +#define HEIGHT 256 +#define WIDTH 1024 + +static void +copy(int fd, uint32_t dst, uint32_t src, uint32_t *all_bo, int n_bo, int alignment, int error) +{ + uint32_t batch[12]; + struct drm_i915_gem_relocation_entry reloc[2]; + struct drm_i915_gem_exec_object2 *obj; + struct drm_i915_gem_execbuffer2 exec; + uint32_t handle; + int n, ret, i=0; + + batch[i++] = (XY_SRC_COPY_BLT_CMD | + XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB | 6); + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + batch[i - 1] += 2; + batch[i++] = (3 << 24) | /* 32 bits */ + (0xcc << 16) | /* copy ROP */ + WIDTH*4; + batch[i++] = 0; /* dst x1,y1 */ + batch[i++] = (HEIGHT << 16) | WIDTH; /* dst x2,y2 */ + batch[i++] = 0; /* dst reloc */ + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + batch[i++] = 0; /* FIXME */ + batch[i++] = 0; /* src x1,y1 */ + batch[i++] = WIDTH*4; + batch[i++] = 0; /* src reloc */ + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + batch[i++] = 0; /* FIXME */ + batch[i++] = MI_BATCH_BUFFER_END; + batch[i++] = MI_NOOP; + + handle = gem_create(fd, 4096); + gem_write(fd, handle, 0, batch, sizeof(batch)); + + reloc[0].target_handle = dst; + reloc[0].delta = 0; + reloc[0].offset = 4 * sizeof(batch[0]); + reloc[0].presumed_offset = 0; + reloc[0].read_domains = I915_GEM_DOMAIN_RENDER; + reloc[0].write_domain = I915_GEM_DOMAIN_RENDER; + + reloc[1].target_handle = src; + reloc[1].delta = 0; + reloc[1].offset = 7 * sizeof(batch[0]); + reloc[1].presumed_offset = 0; + reloc[1].read_domains = I915_GEM_DOMAIN_RENDER; + reloc[1].write_domain = 0; + + obj = calloc(n_bo + 1, sizeof(*obj)); + for (n = 0; n < n_bo; n++) { + obj[n].handle = all_bo[n]; + obj[n].alignment = alignment; + } + obj[n].handle = handle; + obj[n].relocation_count = 2; + obj[n].relocs_ptr = (uintptr_t)reloc; + + exec.buffers_ptr = (uintptr_t)obj; + exec.buffer_count = n_bo + 1; + exec.batch_start_offset = 0; + exec.batch_len = i * 4; + exec.DR1 = exec.DR4 = 0; + exec.num_cliprects = 0; + exec.cliprects_ptr = 0; + exec.flags = HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0; + i915_execbuffer2_set_context_id(exec, 0); + exec.rsvd2 = 0; + + ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); + if (ret) + ret = errno; + igt_assert(ret == error); + + gem_close(fd, handle); + free(obj); +} + +static void minor_evictions(int fd, int size, int count) +{ + uint32_t *bo, *sel; + int n, m, alignment, pass, fail; + + igt_require(intel_check_memory(2*count, size, CHECK_RAM)); + + bo = malloc(3*count*sizeof(*bo)); + igt_assert(bo); + + for (n = 0; n < 2*count; n++) + bo[n] = gem_create(fd, size); + + sel = bo + n; + for (alignment = m = 4096; alignment <= size; alignment <<= 1) { + for (fail = 0; fail < 10; fail++) { + for (pass = 0; pass < 100; pass++) { + for (n = 0; n < count; n++, m += 7) + sel[n] = bo[m%(2*count)]; + copy(fd, sel[0], sel[1], sel, count, alignment, 0); + } + copy(fd, bo[0], bo[0], bo, 2*count, alignment, ENOSPC); + } + } + + for (n = 0; n < 2*count; n++) + gem_close(fd, bo[n]); + free(bo); +} + +static void major_evictions(int fd, int size, int count) +{ + int n, m, loop, alignment, max; + uint32_t *bo; + + igt_require(intel_check_memory(count, size, CHECK_RAM)); + + bo = malloc(count*sizeof(*bo)); + igt_assert(bo); + + for (n = 0; n < count; n++) + bo[n] = gem_create(fd, size); + + max = gem_aperture_size(fd) - size; + for (alignment = m = 4096; alignment < max; alignment <<= 1) { + for (loop = 0; loop < 100; loop++, m += 17) { + n = m % count; + copy(fd, bo[n], bo[n], &bo[n], 1, alignment, 0); + } + } + + for (n = 0; n < count; n++) + gem_close(fd, bo[n]); + free(bo); +} + +int fd; + +igt_main +{ + int size, count; + + igt_skip_on_simulation(); + + igt_fixture { + fd = drm_open_any(); + } + + igt_subtest("minor-normal") { + size = 1024 * 1024; + count = 3*gem_aperture_size(fd) / size / 4; + minor_evictions(fd, size, count); + } + + igt_subtest("major-normal") { + size = 3*gem_aperture_size(fd) / 4; + count = 4; + major_evictions(fd, size, count); + } + + igt_fork_signal_helper(); + igt_subtest("minor-interruptible") { + size = 1024 * 1024; + count = 3*gem_aperture_size(fd) / size / 4; + minor_evictions(fd, size, count); + } + + igt_subtest("major-interruptible") { + size = 3*gem_aperture_size(fd) / 4; + count = 4; + major_evictions(fd, size, count); + } + igt_stop_signal_helper(); + + igt_fixture + close(fd); +} diff --git a/tests/gem_evict_everything.c b/tests/gem_evict_everything.c new file mode 100644 index 00000000..c1eb3bde --- /dev/null +++ b/tests/gem_evict_everything.c @@ -0,0 +1,242 @@ +/* + * Copyright © 2011,2012,2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Chris Wilson <chris@chris-wilson.co.uk> + * Daniel Vetter <daniel.vetter@ffwll.ch> + * + */ + +/* + * Testcase: run a couple of big batches to force the eviction code. + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include "drm.h" +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_chipset.h" + +#include "eviction_common.c" + +#define HEIGHT 256 +#define WIDTH 1024 + +static int +copy(int fd, uint32_t dst, uint32_t src, uint32_t *all_bo, int n_bo) +{ + uint32_t batch[12]; + struct drm_i915_gem_relocation_entry reloc[2]; + struct drm_i915_gem_exec_object2 *obj; + struct drm_i915_gem_execbuffer2 exec; + uint32_t handle; + int n, ret, i=0; + + batch[i++] = (XY_SRC_COPY_BLT_CMD | + XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB | 6); + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + batch[i - 1] += 2; + batch[i++] = (3 << 24) | /* 32 bits */ + (0xcc << 16) | /* copy ROP */ + WIDTH*4; + batch[i++] = 0; /* dst x1,y1 */ + batch[i++] = (HEIGHT << 16) | WIDTH; /* dst x2,y2 */ + batch[i++] = 0; /* dst reloc */ + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + batch[i++] = 0; /* FIXME */ + batch[i++] = 0; /* src x1,y1 */ + batch[i++] = WIDTH*4; + batch[i++] = 0; /* src reloc */ + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + batch[i++] = 0; /* FIXME */ + batch[i++] = MI_BATCH_BUFFER_END; + batch[i++] = MI_NOOP; + + handle = gem_create(fd, 4096); + gem_write(fd, handle, 0, batch, sizeof(batch)); + + reloc[0].target_handle = dst; + reloc[0].delta = 0; + reloc[0].offset = 4 * sizeof(batch[0]); + reloc[0].presumed_offset = 0; + reloc[0].read_domains = I915_GEM_DOMAIN_RENDER; + reloc[0].write_domain = I915_GEM_DOMAIN_RENDER; + + reloc[1].target_handle = src; + reloc[1].delta = 0; + reloc[1].offset = 7 * sizeof(batch[0]); + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + reloc[1].offset += sizeof(batch[0]); + reloc[1].presumed_offset = 0; + reloc[1].read_domains = I915_GEM_DOMAIN_RENDER; + reloc[1].write_domain = 0; + + obj = calloc(n_bo + 1, sizeof(*obj)); + for (n = 0; n < n_bo; n++) + obj[n].handle = all_bo[n]; + obj[n].handle = handle; + obj[n].relocation_count = 2; + obj[n].relocs_ptr = (uintptr_t)reloc; + + exec.buffers_ptr = (uintptr_t)obj; + exec.buffer_count = n_bo + 1; + exec.batch_start_offset = 0; + exec.batch_len = i * 4; + exec.DR1 = exec.DR4 = 0; + exec.num_cliprects = 0; + exec.cliprects_ptr = 0; + exec.flags = HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0; + i915_execbuffer2_set_context_id(exec, 0); + exec.rsvd2 = 0; + + ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); + if (ret) + ret = errno; + + gem_close(fd, handle); + free(obj); + + return ret; +} + +static void clear(int fd, uint32_t handle, int size) +{ + void *base = gem_mmap__cpu(fd, handle, size, PROT_READ | PROT_WRITE); + + igt_assert(base != NULL); + memset(base, 0, size); + munmap(base, size); +} + +static struct igt_eviction_test_ops fault_ops = { + .create = gem_create, + .close = gem_close, + .copy = copy, + .clear = clear, +}; + +static void test_forking_evictions(int fd, int size, int count, + unsigned flags) +{ + int trash_count; + + trash_count = intel_get_total_ram_mb() * 11 / 10; + igt_require(intel_check_memory(trash_count, size, CHECK_RAM | CHECK_SWAP)); + + forking_evictions(fd, &fault_ops, size, count, trash_count, flags); +} + +static void test_swapping_evictions(int fd, int size, int count) +{ + int trash_count; + + trash_count = intel_get_total_ram_mb() * 11 / 10; + igt_require(intel_check_memory(trash_count, size, CHECK_RAM | CHECK_SWAP)); + + swapping_evictions(fd, &fault_ops, size, count, trash_count); +} + +static void test_minor_evictions(int fd, int size, int count) +{ + minor_evictions(fd, &fault_ops, size, count); +} + +static void test_major_evictions(int fd, int size, int count) +{ + major_evictions(fd, &fault_ops, size, count); +} + +igt_main +{ + int size, count, fd; + size = count = 0; + fd = -1; + + igt_skip_on_simulation(); + + igt_fixture { + fd = drm_open_any(); + + size = 1024 * 1024; + count = 3*gem_aperture_size(fd) / size / 4; + } + + for (unsigned flags = 0; flags < ALL_FORKING_EVICTIONS + 1; flags++) { + igt_subtest_f("forked%s%s%s-%s", + flags & FORKING_EVICTIONS_SWAPPING ? "-swapping" : "", + flags & FORKING_EVICTIONS_DUP_DRMFD ? "-multifd" : "", + flags & FORKING_EVICTIONS_MEMORY_PRESSURE ? + "-mempressure" : "", + flags & FORKING_EVICTIONS_INTERRUPTIBLE ? + "interruptible" : "normal") { + test_forking_evictions(fd, size, count, flags); + } + } + + igt_subtest("swapping-normal") + test_swapping_evictions(fd, size, count); + + igt_subtest("minor-normal") + test_minor_evictions(fd, size, count); + + igt_subtest("major-normal") { + size = 3*gem_aperture_size(fd) / 4; + count = 4; + test_major_evictions(fd, size, count); + } + + igt_fixture { + size = 1024 * 1024; + count = 3*gem_aperture_size(fd) / size / 4; + } + + igt_fork_signal_helper(); + + igt_subtest("swapping-interruptible") + test_swapping_evictions(fd, size, count); + + igt_subtest("minor-interruptible") + test_minor_evictions(fd, size, count); + + igt_subtest("major-interruptible") { + size = 3*gem_aperture_size(fd) / 4; + count = 4; + test_major_evictions(fd, size, count); + } + + igt_stop_signal_helper(); + + igt_fixture { + close(fd); + } +} diff --git a/tests/gem_exec_bad_domains.c b/tests/gem_exec_bad_domains.c index f3ee08b7..7641f8f8 100644 --- a/tests/gem_exec_bad_domains.c +++ b/tests/gem_exec_bad_domains.c @@ -28,18 +28,18 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "intel_chipset.h" /* Testcase: Test whether the kernel rejects relocations with non-gpu domains * @@ -72,7 +72,7 @@ run_batch(void) used = batch->ptr - batch->buffer; ret = drm_intel_bo_subdata(batch->bo, 0, used, batch->buffer); - assert(ret == 0); + igt_assert(ret == 0); batch->ptr = NULL; @@ -83,63 +83,150 @@ run_batch(void) return ret; } -int main(int argc, char **argv) +#define I915_GEM_GPU_DOMAINS \ + (I915_GEM_DOMAIN_RENDER | \ + I915_GEM_DOMAIN_SAMPLER | \ + I915_GEM_DOMAIN_COMMAND | \ + I915_GEM_DOMAIN_INSTRUCTION | \ + I915_GEM_DOMAIN_VERTEX) + +static void multi_write_domain(int fd) { - int fd, ret; - drm_intel_bo *tmp; + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 exec[2]; + struct drm_i915_gem_relocation_entry reloc[1]; + uint32_t handle, handle_target; + int ret; - fd = drm_open_any(); + handle = gem_create(fd, 4096); + handle_target = gem_create(fd, 4096); + + exec[0].handle = handle_target; + exec[0].relocation_count = 0; + exec[0].relocs_ptr = 0; + exec[0].alignment = 0; + exec[0].offset = 0; + exec[0].flags = 0; + exec[0].rsvd1 = 0; + exec[0].rsvd2 = 0; + + exec[1].handle = handle; + exec[1].relocation_count = 1; + exec[1].relocs_ptr = (uintptr_t) reloc; + exec[1].alignment = 0; + exec[1].offset = 0; + exec[1].flags = 0; + exec[1].rsvd1 = 0; + exec[1].rsvd2 = 0; + + reloc[0].offset = 4; + reloc[0].delta = 0; + reloc[0].target_handle = handle_target; + reloc[0].read_domains = I915_GEM_DOMAIN_RENDER | I915_GEM_DOMAIN_INSTRUCTION; + reloc[0].write_domain = I915_GEM_DOMAIN_RENDER | I915_GEM_DOMAIN_INSTRUCTION; + reloc[0].presumed_offset = 0; + + execbuf.buffers_ptr = (uintptr_t)exec; + execbuf.buffer_count = 2; + execbuf.batch_start_offset = 0; + execbuf.batch_len = 8; + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = 0; + i915_execbuffer2_set_context_id(execbuf, 0); + execbuf.rsvd2 = 0; + + ret = drmIoctl(fd, + DRM_IOCTL_I915_GEM_EXECBUFFER2, + &execbuf); + igt_assert(ret != 0 && errno == EINVAL); + + gem_close(fd, handle); + gem_close(fd, handle_target); +} - bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - drm_intel_bufmgr_gem_enable_reuse(bufmgr); - batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); +int fd; +drm_intel_bo *tmp; - tmp = drm_intel_bo_alloc(bufmgr, "tmp", 128 * 128, 4096); +igt_main +{ + igt_fixture { + fd = drm_open_any(); - BEGIN_BATCH(2); - OUT_BATCH(0); - OUT_RELOC(tmp, I915_GEM_DOMAIN_CPU, 0, 0); - ADVANCE_BATCH(); - ret = run_batch(); - if (ret != -EINVAL) { - fprintf(stderr, "(cpu, 0) reloc not rejected\n"); - exit(1); + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + drm_intel_bufmgr_gem_enable_reuse(bufmgr); + batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); + + tmp = drm_intel_bo_alloc(bufmgr, "tmp", 128 * 128, 4096); } - BEGIN_BATCH(2); - OUT_BATCH(0); - OUT_RELOC(tmp, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU, 0); - ADVANCE_BATCH(); - ret = run_batch(); - if (ret != -EINVAL) { - fprintf(stderr, "(cpu, cpu) reloc not rejected\n"); - exit(1); + igt_subtest("cpu-domain") { + BEGIN_BATCH(2); + OUT_BATCH(0); + OUT_RELOC(tmp, I915_GEM_DOMAIN_CPU, 0, 0); + ADVANCE_BATCH(); + igt_assert(run_batch() == -EINVAL); + + BEGIN_BATCH(2); + OUT_BATCH(0); + OUT_RELOC(tmp, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU, 0); + ADVANCE_BATCH(); + igt_assert(run_batch() == -EINVAL); } - BEGIN_BATCH(2); - OUT_BATCH(0); - OUT_RELOC(tmp, I915_GEM_DOMAIN_GTT, 0, 0); - ADVANCE_BATCH(); - ret = run_batch(); - if (ret != -EINVAL) { - fprintf(stderr, "(gtt, 0) reloc not rejected\n"); - exit(1); + igt_subtest("gtt-domain") { + BEGIN_BATCH(2); + OUT_BATCH(0); + OUT_RELOC(tmp, I915_GEM_DOMAIN_GTT, 0, 0); + ADVANCE_BATCH(); + igt_assert(run_batch() == -EINVAL); + + BEGIN_BATCH(2); + OUT_BATCH(0); + OUT_RELOC(tmp, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT, 0); + ADVANCE_BATCH(); + igt_assert(run_batch() == -EINVAL); } - BEGIN_BATCH(2); - OUT_BATCH(0); - OUT_RELOC(tmp, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT, 0); - ADVANCE_BATCH(); - ret = run_batch(); - if (ret != -EINVAL) { - fprintf(stderr, "(gtt, gtt) reloc not rejected\n"); - exit(1); + /* Note: Older kernels disallow this. Punt on the skip check though + * since this is too old. */ + igt_subtest("conflicting-write-domain") { + BEGIN_BATCH(4); + OUT_BATCH(0); + OUT_RELOC(tmp, I915_GEM_DOMAIN_RENDER, + I915_GEM_DOMAIN_RENDER, 0); + OUT_BATCH(0); + OUT_RELOC(tmp, I915_GEM_DOMAIN_INSTRUCTION, + I915_GEM_DOMAIN_INSTRUCTION, 0); + ADVANCE_BATCH(); + igt_assert(run_batch() == 0); } - intel_batchbuffer_free(batch); - drm_intel_bufmgr_destroy(bufmgr); + igt_subtest("double-write-domain") + multi_write_domain(fd); + + igt_subtest("invalid-gpu-domain") { + BEGIN_BATCH(2); + OUT_BATCH(0); + OUT_RELOC(tmp, ~(I915_GEM_GPU_DOMAINS | I915_GEM_DOMAIN_GTT | I915_GEM_DOMAIN_CPU), + 0, 0); + ADVANCE_BATCH(); + igt_assert(run_batch() == -EINVAL); + + BEGIN_BATCH(2); + OUT_BATCH(0); + OUT_RELOC(tmp, I915_GEM_DOMAIN_GTT << 1, + I915_GEM_DOMAIN_GTT << 1, 0); + ADVANCE_BATCH(); + igt_assert(run_batch() == -EINVAL); + } - close(fd); + igt_fixture { + intel_batchbuffer_free(batch); + drm_intel_bufmgr_destroy(bufmgr); - return 0; + close(fd); + } } diff --git a/tests/gem_exec_big.c b/tests/gem_exec_big.c new file mode 100644 index 00000000..70753164 --- /dev/null +++ b/tests/gem_exec_big.c @@ -0,0 +1,123 @@ +/* + * Copyright © 2011,2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Chris Wilson <chris@chris-wilson.co.uk> + * Daniel Vetter <daniel.vetter@ffwll.ch> + * + */ + +/* + * Testcase: run a nop batch which is really big + * + * Mostly useful to stress-test the error-capture code + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include "drm.h" +#include "ioctl_wrappers.h" +#include "drmtest.h" + +#define BATCH_SIZE (1024*1024) + +static int exec(int fd, uint32_t handle, uint32_t reloc_ofs) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 gem_exec[1]; + struct drm_i915_gem_relocation_entry gem_reloc[1]; + uint32_t tmp; + int ret = 0; + + gem_reloc[0].offset = reloc_ofs; + gem_reloc[0].delta = 0; + gem_reloc[0].target_handle = handle; + gem_reloc[0].read_domains = I915_GEM_DOMAIN_RENDER; + gem_reloc[0].write_domain = 0; + gem_reloc[0].presumed_offset = 0; + + gem_exec[0].handle = handle; + gem_exec[0].relocation_count = 1; + gem_exec[0].relocs_ptr = (uintptr_t) gem_reloc; + gem_exec[0].alignment = 0; + gem_exec[0].offset = 0; + gem_exec[0].flags = 0; + gem_exec[0].rsvd1 = 0; + gem_exec[0].rsvd2 = 0; + + execbuf.buffers_ptr = (uintptr_t)gem_exec; + execbuf.buffer_count = 1; + execbuf.batch_start_offset = 0; + execbuf.batch_len = 8; + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = 0; + i915_execbuffer2_set_context_id(execbuf, 0); + execbuf.rsvd2 = 0; + + ret = drmIoctl(fd, + DRM_IOCTL_I915_GEM_EXECBUFFER2, + &execbuf); + gem_sync(fd, handle); + + gem_read(fd, handle, reloc_ofs, &tmp, 4); + + igt_assert(tmp == gem_reloc[0].presumed_offset); + + return ret; +} + +igt_simple_main +{ + uint32_t batch[2] = {MI_BATCH_BUFFER_END}; + uint32_t handle; + int fd; + uint32_t reloc_ofs; + unsigned batch_size; + + igt_skip_on_simulation(); + + fd = drm_open_any(); + + for (batch_size = BATCH_SIZE/4; batch_size <= BATCH_SIZE; batch_size += 4096) { + handle = gem_create(fd, batch_size); + gem_write(fd, handle, 0, batch, sizeof(batch)); + + for (reloc_ofs = 4096; reloc_ofs < batch_size; reloc_ofs += 4096) + igt_assert(exec(fd, handle, reloc_ofs) == 0); + } + + gem_close(fd, handle); + + close(fd); +} diff --git a/tests/gem_exec_blt.c b/tests/gem_exec_blt.c index eb5ae668..3bcef183 100644 --- a/tests/gem_exec_blt.c +++ b/tests/gem_exec_blt.c @@ -30,19 +30,17 @@ #include <stdint.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/ioctl.h> -#include <sys/mman.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_chipset.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" #define OBJECT_SIZE 16384 @@ -52,7 +50,8 @@ #define BLT_SRC_TILED (1<<15) #define BLT_DST_TILED (1<<11) -static int gem_linear_blt(uint32_t *batch, +static int gem_linear_blt(int fd, + uint32_t *batch, uint32_t src, uint32_t dst, uint32_t length, @@ -61,14 +60,17 @@ static int gem_linear_blt(uint32_t *batch, uint32_t *b = batch; int height = length / (16 * 1024); - assert(height <= 1<<16); + igt_assert(height <= 1<<16); if (height) { - b[0] = COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB; - b[1] = 0xcc << 16 | 1 << 25 | 1 << 24 | (16*1024); - b[2] = 0; - b[3] = height << 16 | (4*1024); - b[4] = 0; + int i = 0; + b[i++] = COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB; + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + b[i-1]+=2; + b[i++] = 0xcc << 16 | 1 << 25 | 1 << 24 | (16*1024); + b[i++] = 0; + b[i++] = height << 16 | (4*1024); + b[i++] = 0; reloc->offset = (b-batch+4) * sizeof(uint32_t); reloc->delta = 0; reloc->target_handle = dst; @@ -76,28 +78,37 @@ static int gem_linear_blt(uint32_t *batch, reloc->write_domain = I915_GEM_DOMAIN_RENDER; reloc->presumed_offset = 0; reloc++; + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + b[i++] = 0; /* FIXME */ - b[5] = 0; - b[6] = 16*1024; - b[7] = 0; + b[i++] = 0; + b[i++] = 16*1024; + b[i++] = 0; reloc->offset = (b-batch+7) * sizeof(uint32_t); + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + reloc->offset += sizeof(uint32_t); reloc->delta = 0; reloc->target_handle = src; reloc->read_domains = I915_GEM_DOMAIN_RENDER; reloc->write_domain = 0; reloc->presumed_offset = 0; reloc++; + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + b[i++] = 0; /* FIXME */ - b += 8; + b += i; length -= height * 16*1024; } - + if (length) { - b[0] = COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB; - b[1] = 0xcc << 16 | 1 << 25 | 1 << 24 | (16*1024); - b[2] = height << 16; - b[3] = (1+height) << 16 | (length / 4); - b[4] = 0; + int i = 0; + b[i++] = COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB; + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + b[i-1]+=2; + b[i++] = 0xcc << 16 | 1 << 25 | 1 << 24 | (16*1024); + b[i++] = height << 16; + b[i++] = (1+height) << 16 | (length / 4); + b[i++] = 0; reloc->offset = (b-batch+4) * sizeof(uint32_t); reloc->delta = 0; reloc->target_handle = dst; @@ -105,19 +116,25 @@ static int gem_linear_blt(uint32_t *batch, reloc->write_domain = I915_GEM_DOMAIN_RENDER; reloc->presumed_offset = 0; reloc++; + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + b[i++] = 0; /* FIXME */ - b[5] = height << 16; - b[6] = 16*1024; - b[7] = 0; + b[i++] = height << 16; + b[i++] = 16*1024; + b[i++] = 0; reloc->offset = (b-batch+7) * sizeof(uint32_t); + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + reloc->offset += sizeof(uint32_t); reloc->delta = 0; reloc->target_handle = src; reloc->read_domains = I915_GEM_DOMAIN_RENDER; reloc->write_domain = 0; reloc->presumed_offset = 0; reloc++; + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + b[i++] = 0; /* FIXME */ - b += 8; + b += i; } b[0] = MI_BATCH_BUFFER_END; @@ -126,19 +143,6 @@ static int gem_linear_blt(uint32_t *batch, return (b+2 - batch) * sizeof(uint32_t); } -static int gem_exec(int fd, struct drm_i915_gem_execbuffer2 *execbuf, int loops) -{ - int ret = 0; - - while (loops-- && ret == 0) { - ret = drmIoctl(fd, - DRM_IOCTL_I915_GEM_EXECBUFFER2, - execbuf); - } - - return ret; -} - static double elapsed(const struct timeval *start, const struct timeval *end, int loop) @@ -181,7 +185,7 @@ static void run(int object_size) src = gem_create(fd, object_size); dst = gem_create(fd, object_size); - len = gem_linear_blt(buf, src, dst, object_size, reloc); + len = gem_linear_blt(fd, buf, src, dst, object_size, reloc); gem_write(fd, handle, 0, buf, len); exec[0].handle = src; @@ -203,7 +207,10 @@ static void run(int object_size) exec[1].rsvd2 = 0; exec[2].handle = handle; - exec[2].relocation_count = len > 40 ? 4 : 2; + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + exec[2].relocation_count = len > 56 ? 4 : 2; + else + exec[2].relocation_count = len > 40 ? 4 : 2; exec[2].relocs_ptr = (uintptr_t)reloc; exec[2].alignment = 0; exec[2].offset = 0; @@ -227,18 +234,18 @@ static void run(int object_size) i915_execbuffer2_set_context_id(execbuf, 0); execbuf.rsvd2 = 0; - for (count = 1; count <= 1<<17; count <<= 1) { + for (count = 1; count <= 1<<12; count <<= 1) { struct timeval start, end; gettimeofday(&start, NULL); - if (gem_exec(fd, &execbuf, count)) - exit(1); + for (int loop = 0; loop < count; loop++) + gem_execbuf(fd, &execbuf); gem_sync(fd, handle); gettimeofday(&end, NULL); - printf("Time to blt %d bytes x %6d: %7.3fµs, %s\n", - object_size, count, - elapsed(&start, &end, count), - bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6)); + igt_info("Time to blt %d bytes x %6d: %7.3fµs, %s\n", + object_size, count, + elapsed(&start, &end, count), + bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6)); fflush(stdout); } gem_close(fd, handle); @@ -250,6 +257,10 @@ int main(int argc, char **argv) { int i; + igt_simple_init(); + + igt_skip_on_simulation(); + if (argc > 1) { for (i = 1; i < argc; i++) { int object_size = atoi(argv[i]); diff --git a/tests/gem_exec_faulting_reloc.c b/tests/gem_exec_faulting_reloc.c index 863a1b03..acd703b6 100644 --- a/tests/gem_exec_faulting_reloc.c +++ b/tests/gem_exec_faulting_reloc.c @@ -30,19 +30,18 @@ #include <stdint.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/ioctl.h> -#include <sys/mman.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_chipset.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "igt_debugfs.h" /* Testcase: Submit patches with relocations in memory that will fault * @@ -51,12 +50,14 @@ #define OBJECT_SIZE 16384 -#define COPY_BLT_CMD (2<<29|0x53<<22|0x6) +#define COPY_BLT_CMD_NOLEN (2<<29|0x53<<22) #define BLT_WRITE_ALPHA (1<<21) #define BLT_WRITE_RGB (1<<20) #define BLT_SRC_TILED (1<<15) #define BLT_DST_TILED (1<<11) +uint32_t devid; + static int gem_linear_blt(uint32_t *batch, uint32_t src, uint32_t dst, @@ -66,14 +67,19 @@ static int gem_linear_blt(uint32_t *batch, uint32_t *b = batch; int height = length / (16 * 1024); - assert(height <= 1<<16); + igt_assert(height <= 1<<16); if (height) { - b[0] = COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB; - b[1] = 0xcc << 16 | 1 << 25 | 1 << 24 | (16*1024); - b[2] = 0; - b[3] = height << 16 | (4*1024); - b[4] = 0; + int i = 0; + b[i++] = COPY_BLT_CMD_NOLEN | BLT_WRITE_ALPHA | BLT_WRITE_RGB; + if (intel_gen(devid) >= 8) + b[i-1] |= 8; + else + b[i-1] |= 6; + b[i++] = 0xcc << 16 | 1 << 25 | 1 << 24 | (16*1024); + b[i++] = 0; + b[i++] = height << 16 | (4*1024); + b[i++] = 0; reloc->offset = (b-batch+4) * sizeof(uint32_t); reloc->delta = 0; reloc->target_handle = dst; @@ -82,10 +88,17 @@ static int gem_linear_blt(uint32_t *batch, reloc->presumed_offset = 0; reloc++; - b[5] = 0; - b[6] = 16*1024; - b[7] = 0; + if (intel_gen(devid) >= 8) + b[i++] = 0; /* FIXME: use real high dword */ + + b[i++] = 0; + b[i++] = 16*1024; + b[i++] = 0; reloc->offset = (b-batch+7) * sizeof(uint32_t); + if (intel_gen(devid) >= 8) { + reloc->offset += sizeof(uint32_t); + b[i++] = 0; /* FIXME: use real high dword */ + } reloc->delta = 0; reloc->target_handle = src; reloc->read_domains = I915_GEM_DOMAIN_RENDER; @@ -93,16 +106,24 @@ static int gem_linear_blt(uint32_t *batch, reloc->presumed_offset = 0; reloc++; - b += 8; + if (intel_gen(devid) >= 8) + b += 10; + else + b += 8; length -= height * 16*1024; } if (length) { - b[0] = COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB; - b[1] = 0xcc << 16 | 1 << 25 | 1 << 24 | (16*1024); - b[2] = height << 16; - b[3] = (1+height) << 16 | (length / 4); - b[4] = 0; + int i = 0; + b[i++] = COPY_BLT_CMD_NOLEN | BLT_WRITE_ALPHA | BLT_WRITE_RGB; + if (intel_gen(devid) >= 8) + b[i-1] |= 8; + else + b[i-1] |= 6; + b[i++] = 0xcc << 16 | 1 << 25 | 1 << 24 | (16*1024); + b[i++] = height << 16; + b[i++] = (1+height) << 16 | (length / 4); + b[i++] = 0; reloc->offset = (b-batch+4) * sizeof(uint32_t); reloc->delta = 0; reloc->target_handle = dst; @@ -110,11 +131,17 @@ static int gem_linear_blt(uint32_t *batch, reloc->write_domain = I915_GEM_DOMAIN_RENDER; reloc->presumed_offset = 0; reloc++; + if (intel_gen(devid) >= 8) + b[i++] = 0; /* FIXME: use real high dword */ - b[5] = height << 16; - b[6] = 16*1024; - b[7] = 0; + b[i++] = height << 16; + b[i++] = 16*1024; + b[i++] = 0; reloc->offset = (b-batch+7) * sizeof(uint32_t); + if (intel_gen(devid) >= 8) { + reloc->offset += sizeof(uint32_t); + b[i++] = 0; /* FIXME: use real high dword */ + } reloc->delta = 0; reloc->target_handle = src; reloc->read_domains = I915_GEM_DOMAIN_RENDER; @@ -122,7 +149,10 @@ static int gem_linear_blt(uint32_t *batch, reloc->presumed_offset = 0; reloc++; - b += 8; + if (intel_gen(devid) >= 8) + b += 10; + else + b += 8; } b[0] = MI_BATCH_BUFFER_END; @@ -131,28 +161,19 @@ static int gem_linear_blt(uint32_t *batch, return (b+2 - batch) * sizeof(uint32_t); } -static void gem_exec(int fd, struct drm_i915_gem_execbuffer2 *execbuf) -{ - int ret; - - ret = drmIoctl(fd, - DRM_IOCTL_I915_GEM_EXECBUFFER2, - execbuf); - assert(ret == 0); -} - static void run(int object_size) { struct drm_i915_gem_execbuffer2 execbuf; struct drm_i915_gem_exec_object2 exec[3]; struct drm_i915_gem_relocation_entry reloc[4]; - uint32_t buf[20]; + uint32_t buf[40]; uint32_t handle, handle_relocs, src, dst; void *gtt_relocs; int fd, len; int ring; fd = drm_open_any(); + devid = intel_get_drm_devid(fd); handle = gem_create(fd, 4096); src = gem_create(fd, object_size); dst = gem_create(fd, object_size); @@ -182,10 +203,13 @@ static void run(int object_size) gem_write(fd, handle_relocs, 0, reloc, sizeof(reloc)); gtt_relocs = gem_mmap(fd, handle_relocs, 4096, PROT_READ | PROT_WRITE); - assert(gtt_relocs); + igt_assert(gtt_relocs); exec[2].handle = handle; - exec[2].relocation_count = len > 40 ? 4 : 2; + if (intel_gen(devid) >= 8) + exec[2].relocation_count = len > 56 ? 4 : 2; + else + exec[2].relocation_count = len > 40 ? 4 : 2; /* A newly mmap gtt bo will fault on first access. */ exec[2].relocs_ptr = (uintptr_t)gtt_relocs; exec[2].alignment = 0; @@ -195,7 +219,7 @@ static void run(int object_size) exec[2].rsvd2 = 0; ring = 0; - if (HAS_BLT_RING(intel_get_drm_devid(fd))) + if (HAS_BLT_RING(devid)) ring = I915_EXEC_BLT; execbuf.buffers_ptr = (uintptr_t)exec; @@ -210,7 +234,7 @@ static void run(int object_size) i915_execbuffer2_set_context_id(execbuf, 0); execbuf.rsvd2 = 0; - gem_exec(fd, &execbuf); + gem_execbuf(fd, &execbuf); gem_sync(fd, handle); gem_close(fd, handle); @@ -218,9 +242,13 @@ static void run(int object_size) close(fd); } -int main(int argc, char **argv) +igt_main { - run(OBJECT_SIZE); - - return 0; + igt_subtest("normal") + run(OBJECT_SIZE); + igt_subtest("no-prefault") { + igt_disable_prefault(); + run(OBJECT_SIZE); + igt_enable_prefault(); + } } diff --git a/tests/gem_exec_lut_handle.c b/tests/gem_exec_lut_handle.c new file mode 100644 index 00000000..6ee75274 --- /dev/null +++ b/tests/gem_exec_lut_handle.c @@ -0,0 +1,204 @@ +/* + * Copyright © 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Chris Wilson <chris@chris-wilson.co.uk> + * + */ + +/* Exercises the basic execbuffer using theh andle LUT interface */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> +#include "drm.h" +#include "ioctl_wrappers.h" +#include "drmtest.h" + +#define BATCH_SIZE (1024*1024) + +#define LOCAL_I915_EXEC_NO_RELOC (1<<11) +#define LOCAL_I915_EXEC_HANDLE_LUT (1<<12) + +#define MAX_NUM_EXEC 2048 +#define MAX_NUM_RELOC 4096 + +#define USE_LUT 0x1 +#define SKIP_RELOC 0x2 +#define NO_RELOC 0x4 + +struct drm_i915_gem_exec_object2 gem_exec[MAX_NUM_EXEC+1]; +struct drm_i915_gem_relocation_entry gem_reloc[MAX_NUM_RELOC]; + +static uint32_t state = 0x12345678; + +static uint32_t +hars_petruska_f54_1_random (void) +{ +#define rol(x,k) ((x << k) | (x >> (32-k))) + return state = (state ^ rol (state, 5) ^ rol (state, 24)) + 0x37798849; +#undef rol +} + + +static int exec(int fd, int num_exec, int num_relocs, unsigned flags) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 *objects; + int i; + + gem_exec[MAX_NUM_EXEC].relocation_count = num_relocs; + gem_exec[MAX_NUM_EXEC].relocs_ptr = (uintptr_t) gem_reloc; + + objects = gem_exec + MAX_NUM_EXEC - num_exec; + + for (i = 0; i < num_relocs; i++) { + int target = hars_petruska_f54_1_random() % num_exec; + gem_reloc[i].offset = 1024; + gem_reloc[i].delta = 0; + gem_reloc[i].target_handle = + flags & USE_LUT ? target : objects[target].handle; + gem_reloc[i].read_domains = I915_GEM_DOMAIN_RENDER; + gem_reloc[i].write_domain = 0; + gem_reloc[i].presumed_offset = 0; + if (flags & SKIP_RELOC) + gem_reloc[i].presumed_offset = objects[target].offset; + } + + execbuf.buffers_ptr = (uintptr_t)objects; + execbuf.buffer_count = num_exec + 1; + execbuf.batch_start_offset = 0; + execbuf.batch_len = 8; + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = 0; + if (flags & USE_LUT) + execbuf.flags |= LOCAL_I915_EXEC_HANDLE_LUT; + if (flags & NO_RELOC) + execbuf.flags |= LOCAL_I915_EXEC_NO_RELOC; + i915_execbuffer2_set_context_id(execbuf, 0); + execbuf.rsvd2 = 0; + + return drmIoctl(fd, + DRM_IOCTL_I915_GEM_EXECBUFFER2, + &execbuf); +} + +#define ELAPSED(a,b) (1e6*((b)->tv_sec - (a)->tv_sec) + ((b)->tv_usec - (a)->tv_usec)) +igt_simple_main +{ + uint32_t batch[2] = {MI_BATCH_BUFFER_END}; + int fd, n, m, count; + const struct { + const char *name; + unsigned int flags; + } pass[] = { + { .name = "relocation", .flags = 0 }, + { .name = "skip-relocs", .flags = SKIP_RELOC }, + { .name = "no-relocs", .flags = NO_RELOC }, + { .name = NULL }, + }, *p; + + igt_skip_on_simulation(); + + fd = drm_open_any(); + + for (n = 0; n < MAX_NUM_EXEC; n++) { + gem_exec[n].handle = gem_create(fd, 4096); + gem_exec[n].relocation_count = 0; + gem_exec[n].relocs_ptr = 0; + gem_exec[n].alignment = 0; + gem_exec[n].offset = 0; + gem_exec[n].flags = 0; + gem_exec[n].rsvd1 = 0; + gem_exec[n].rsvd2 = 0; + } + + gem_exec[n].handle = gem_create(fd, 4096); + gem_write(fd, gem_exec[n].handle, 0, batch, sizeof(batch)); + + igt_skip_on(exec(fd, 1, 0, USE_LUT)); + + for (p = pass; p->name != NULL; p++) { + for (n = 1; n <= MAX_NUM_EXEC; n *= 2) { + double elapsed[16][2]; + double s_x, s_y, s_xx, s_xy; + double A, B; + int i, j; + + for (i = 0, m = 1; m <= MAX_NUM_RELOC; m *= 2, i++) { + struct timeval start, end; + + do_or_die(exec(fd, n, m, 0 | p->flags)); + gettimeofday(&start, NULL); + for (count = 0; count < 1000; count++) + do_or_die(exec(fd, n, m, 0 | p->flags)); + gettimeofday(&end, NULL); + gem_sync(fd, gem_exec[MAX_NUM_EXEC].handle); + elapsed[i][0] = ELAPSED(&start, &end); + + do_or_die(exec(fd, n, m, USE_LUT | p->flags)); + gettimeofday(&start, NULL); + for (count = 0; count < 1000; count++) + do_or_die(exec(fd, n, m, USE_LUT | p->flags)); + gettimeofday(&end, NULL); + gem_sync(fd, gem_exec[MAX_NUM_EXEC].handle); + elapsed[i][1] = ELAPSED(&start, &end); + } + + igt_info("%s: buffers=%4d:", p->name, n); + + s_x = s_y = s_xx = s_xy = 0; + for (j = 0; j < i; j++) { + int k = 1 << j; + s_x += k; + s_y += elapsed[j][0]; + s_xx += k * k; + s_xy += k * elapsed[j][0]; + } + B = (s_xy - s_x * s_y / j) / (s_xx - s_x * s_x / j); + A = s_y / j - B * s_x / j; + igt_info(" old=%7.0f + %.1f*reloc,", A, B); + + s_x = s_y = s_xx = s_xy = 0; + for (j = 0; j < i; j++) { + int k = 1 << j; + s_x += k; + s_y += elapsed[j][1]; + s_xx += k * k; + s_xy += k * elapsed[j][1]; + } + B = (s_xy - s_x * s_y / j) / (s_xx - s_x * s_x / j); + A = s_y / j - B * s_x / j; + igt_info(" lut=%7.0f + %.1f*reloc (ns)", A, B); + + igt_info("\n"); + } + } +} diff --git a/tests/gem_exec_nop.c b/tests/gem_exec_nop.c index 9dd055cf..542f98c3 100644 --- a/tests/gem_exec_nop.c +++ b/tests/gem_exec_nop.c @@ -30,19 +30,18 @@ #include <stdint.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/ioctl.h> -#include <sys/mman.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" +#include "intel_io.h" -#define MI_BATCH_BUFFER_END (0xA<<23) +#define LOCAL_I915_EXEC_VEBOX (4<<0) static double elapsed(const struct timeval *start, const struct timeval *end, @@ -51,7 +50,7 @@ static double elapsed(const struct timeval *start, return (1e6*(end->tv_sec - start->tv_sec) + (end->tv_usec - start->tv_usec))/loop; } -static int exec(int fd, uint32_t handle, int loops) +static int exec(int fd, uint32_t handle, int loops, unsigned ring_id) { struct drm_i915_gem_execbuffer2 execbuf; struct drm_i915_gem_exec_object2 gem_exec[1]; @@ -74,7 +73,7 @@ static int exec(int fd, uint32_t handle, int loops) execbuf.num_cliprects = 0; execbuf.DR1 = 0; execbuf.DR4 = 0; - execbuf.flags = 0; + execbuf.flags = ring_id; i915_execbuffer2_set_context_id(execbuf, 0); execbuf.rsvd2 = 0; @@ -88,32 +87,52 @@ static int exec(int fd, uint32_t handle, int loops) return ret; } -int main(int argc, char **argv) +static void loop(int fd, uint32_t handle, unsigned ring_id, const char *ring_name) { - uint32_t batch[2] = {MI_BATCH_BUFFER_END}; - uint32_t handle; int count; - int fd; - fd = drm_open_any(); + gem_require_ring(fd, ring_id); - handle = gem_create(fd, 4096); - gem_write(fd, handle, 0, batch, sizeof(batch)); - - for (count = 1; count <= 1<<17; count <<= 1) { + for (count = 1; count <= SLOW_QUICK(1<<17, 1<<4); count <<= 1) { struct timeval start, end; gettimeofday(&start, NULL); - if (exec(fd, handle, count)) - exit(1); + igt_assert(exec(fd, handle, count, ring_id) == 0); gettimeofday(&end, NULL); - printf("Time to exec x %d: %7.3fµs\n", - count, elapsed(&start, &end, count)); + igt_info("Time to exec x %d: %7.3fµs (ring=%s)\n", + count, elapsed(&start, &end, count), ring_name); fflush(stdout); } - gem_close(fd, handle); +} + +uint32_t batch[2] = {MI_BATCH_BUFFER_END}; +uint32_t handle; +int fd; + +igt_main +{ + igt_fixture { + fd = drm_open_any(); + + handle = gem_create(fd, 4096); + gem_write(fd, handle, 0, batch, sizeof(batch)); + } + + igt_subtest("render") + loop(fd, handle, I915_EXEC_RENDER, "render"); + + igt_subtest("bsd") + loop(fd, handle, I915_EXEC_BSD, "bsd"); - close(fd); + igt_subtest("blt") + loop(fd, handle, I915_EXEC_BLT, "blt"); - return 0; + igt_subtest("vebox") + loop(fd, handle, LOCAL_I915_EXEC_VEBOX, "vebox"); + + igt_fixture { + gem_close(fd, handle); + + close(fd); + } } diff --git a/tests/gem_exec_params.c b/tests/gem_exec_params.c new file mode 100644 index 00000000..769969d3 --- /dev/null +++ b/tests/gem_exec_params.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Daniel Vetter + * + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include "drm.h" + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_io.h" +#include "intel_chipset.h" +#include "igt_aux.h" + +#define LOCAL_I915_EXEC_VEBOX (4<<0) + +struct drm_i915_gem_execbuffer2 execbuf; +struct drm_i915_gem_exec_object2 gem_exec[1]; +uint32_t batch[2] = {MI_BATCH_BUFFER_END}; +uint32_t handle, devid; +int fd; + +igt_main +{ + igt_fixture { + fd = drm_open_any(); + + devid = intel_get_drm_devid(fd); + + handle = gem_create(fd, 4096); + gem_write(fd, handle, 0, batch, sizeof(batch)); + + gem_exec[0].handle = handle; + gem_exec[0].relocation_count = 0; + gem_exec[0].relocs_ptr = 0; + gem_exec[0].alignment = 0; + gem_exec[0].offset = 0; + gem_exec[0].flags = 0; + gem_exec[0].rsvd1 = 0; + gem_exec[0].rsvd2 = 0; + + execbuf.buffers_ptr = (uintptr_t)gem_exec; + execbuf.buffer_count = 1; + execbuf.batch_start_offset = 0; + execbuf.batch_len = 8; + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = 0; + i915_execbuffer2_set_context_id(execbuf, 0); + execbuf.rsvd2 = 0; + } + + igt_subtest("control") { + igt_assert(drmIoctl(fd, + DRM_IOCTL_I915_GEM_EXECBUFFER2, + &execbuf) == 0); + execbuf.flags = I915_EXEC_RENDER; + igt_assert(drmIoctl(fd, + DRM_IOCTL_I915_GEM_EXECBUFFER2, + &execbuf) == 0); + } + +#define RUN_FAIL(expected_errno) do { \ + igt_assert(drmIoctl(fd, \ + DRM_IOCTL_I915_GEM_EXECBUFFER2, \ + &execbuf) == -1); \ + igt_assert_cmpint(errno, ==, expected_errno); \ + } while(0) + + igt_subtest("no-bsd") { + igt_require(!gem_has_bsd(fd)); + execbuf.flags = I915_EXEC_BSD; + RUN_FAIL(EINVAL); + } + igt_subtest("no-blt") { + igt_require(!gem_has_blt(fd)); + execbuf.flags = I915_EXEC_BLT; + RUN_FAIL(EINVAL); + } + igt_subtest("no-vebox") { + igt_require(!gem_has_vebox(fd)); + execbuf.flags = LOCAL_I915_EXEC_VEBOX; + RUN_FAIL(EINVAL); + } + igt_subtest("invalid-ring") { + execbuf.flags = I915_EXEC_RING_MASK; + RUN_FAIL(EINVAL); + } + + igt_subtest("invalid-ring2") { + execbuf.flags = LOCAL_I915_EXEC_VEBOX+1; + RUN_FAIL(EINVAL); + } + + igt_subtest("rel-constants-invalid-ring") { + igt_require(gem_has_bsd(fd)); + execbuf.flags = I915_EXEC_BSD | I915_EXEC_CONSTANTS_ABSOLUTE; + RUN_FAIL(EINVAL); + } + + igt_subtest("rel-constants-invalid-rel-gen5") { + igt_require(intel_gen(devid) > 5); + execbuf.flags = I915_EXEC_RENDER | I915_EXEC_CONSTANTS_REL_SURFACE; + RUN_FAIL(EINVAL); + } + + igt_subtest("rel-constants-invalid") { + execbuf.flags = I915_EXEC_RENDER | (I915_EXEC_CONSTANTS_REL_SURFACE+(1<<6)); + RUN_FAIL(EINVAL); + } + + igt_subtest("sol-reset-invalid") { + igt_require(gem_has_bsd(fd)); + execbuf.flags = I915_EXEC_BSD | I915_EXEC_GEN7_SOL_RESET; + RUN_FAIL(EINVAL); + } + + igt_subtest("sol-reset-not-gen7") { + igt_require(intel_gen(devid) != 7); + execbuf.flags = I915_EXEC_RENDER | I915_EXEC_GEN7_SOL_RESET; + RUN_FAIL(EINVAL); + } + + igt_subtest("secure-non-root") { + igt_fork(child, 1) { + igt_drop_root(); + + execbuf.flags = I915_EXEC_RENDER | I915_EXEC_SECURE; + RUN_FAIL(EPERM); + } + + igt_waitchildren(); + } + + igt_subtest("secure-non-master") { + do_or_die(drmDropMaster(fd)); + execbuf.flags = I915_EXEC_RENDER | I915_EXEC_SECURE; + RUN_FAIL(EPERM); + do_or_die(drmSetMaster(fd)); + igt_assert(drmIoctl(fd, + DRM_IOCTL_I915_GEM_EXECBUFFER2, + &execbuf) == 0); + } + + /* HANDLE_LUT and NO_RELOC are already exercised by gem_exec_lut_handle */ + + igt_subtest("invalid-flag") { + execbuf.flags = I915_EXEC_RENDER | (I915_EXEC_HANDLE_LUT << 1); + RUN_FAIL(EINVAL); + } + + /* rsvd1 aka context id is already exercised by gem_ctx_bad_exec */ + + igt_subtest("cliprects-invalid") { + igt_require(intel_gen(devid) >= 5); + execbuf.flags = 0; + execbuf.num_cliprects = 1; + RUN_FAIL(EINVAL); + execbuf.num_cliprects = 0; + } + +#define DIRT(name) \ + igt_subtest(#name "-dirt") { \ + execbuf.flags = 0; \ + execbuf.name = 1; \ + RUN_FAIL(EINVAL); \ + execbuf.name = 0; \ + } + + DIRT(rsvd2); + DIRT(cliprects_ptr); + DIRT(DR1); + DIRT(DR4); +#undef DIRT + +#undef RUN_FAIL + + igt_fixture { + gem_close(fd, handle); + + close(fd); + } +} diff --git a/tests/gem_exec_parse.c b/tests/gem_exec_parse.c new file mode 100644 index 00000000..35d579d6 --- /dev/null +++ b/tests/gem_exec_parse.c @@ -0,0 +1,397 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <errno.h> + +#include <drm.h> + +#include "drmtest.h" +#include "ioctl_wrappers.h" +#include "intel_chipset.h" + +#ifndef I915_PARAM_CMD_PARSER_VERSION +#define I915_PARAM_CMD_PARSER_VERSION 28 +#endif + +static int exec_batch_patched(int fd, uint32_t cmd_bo, uint32_t *cmds, + int size, int patch_offset, uint64_t expected_value) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 objs[2]; + struct drm_i915_gem_relocation_entry reloc[1]; + + uint32_t target_bo = gem_create(fd, 4096); + uint64_t actual_value = 0; + + gem_write(fd, cmd_bo, 0, cmds, size); + + reloc[0].offset = patch_offset; + reloc[0].delta = 0; + reloc[0].target_handle = target_bo; + reloc[0].read_domains = I915_GEM_DOMAIN_RENDER; + reloc[0].write_domain = I915_GEM_DOMAIN_RENDER; + reloc[0].presumed_offset = 0; + + objs[0].handle = target_bo; + objs[0].relocation_count = 0; + objs[0].relocs_ptr = 0; + objs[0].alignment = 0; + objs[0].offset = 0; + objs[0].flags = 0; + objs[0].rsvd1 = 0; + objs[0].rsvd2 = 0; + + objs[1].handle = cmd_bo; + objs[1].relocation_count = 1; + objs[1].relocs_ptr = (uintptr_t)reloc; + objs[1].alignment = 0; + objs[1].offset = 0; + objs[1].flags = 0; + objs[1].rsvd1 = 0; + objs[1].rsvd2 = 0; + + execbuf.buffers_ptr = (uintptr_t)objs; + execbuf.buffer_count = 2; + execbuf.batch_start_offset = 0; + execbuf.batch_len = size; + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = I915_EXEC_RENDER; + i915_execbuffer2_set_context_id(execbuf, 0); + execbuf.rsvd2 = 0; + + gem_execbuf(fd, &execbuf); + gem_sync(fd, cmd_bo); + + gem_read(fd,target_bo, 0, &actual_value, sizeof(actual_value)); + igt_assert(expected_value == actual_value); + + gem_close(fd, target_bo); + + return 1; +} + +static int exec_batch(int fd, uint32_t cmd_bo, uint32_t *cmds, + int size, int ring, int expected_ret) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 objs[1]; + int ret; + + gem_write(fd, cmd_bo, 0, cmds, size); + + objs[0].handle = cmd_bo; + objs[0].relocation_count = 0; + objs[0].relocs_ptr = 0; + objs[0].alignment = 0; + objs[0].offset = 0; + objs[0].flags = 0; + objs[0].rsvd1 = 0; + objs[0].rsvd2 = 0; + + execbuf.buffers_ptr = (uintptr_t)objs; + execbuf.buffer_count = 1; + execbuf.batch_start_offset = 0; + execbuf.batch_len = size; + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = ring; + i915_execbuffer2_set_context_id(execbuf, 0); + execbuf.rsvd2 = 0; + + ret = drmIoctl(fd, + DRM_IOCTL_I915_GEM_EXECBUFFER2, + &execbuf); + if (ret == 0) + igt_assert(expected_ret == 0); + else + igt_assert(-errno == expected_ret); + + gem_sync(fd, cmd_bo); + + return 1; +} + +static int exec_split_batch(int fd, uint32_t *cmds, + int size, int ring, int expected_ret) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 objs[1]; + uint32_t cmd_bo; + uint32_t noop[1024] = { 0 }; + int ret; + + // Allocate and fill a 2-page batch with noops + cmd_bo = gem_create(fd, 4096 * 2); + gem_write(fd, cmd_bo, 0, noop, sizeof(noop)); + gem_write(fd, cmd_bo, 4096, noop, sizeof(noop)); + + // Write the provided commands such that the first dword + // of the command buffer is the last dword of the first + // page (i.e. the command is split across the two pages). + gem_write(fd, cmd_bo, 4096-sizeof(uint32_t), cmds, size); + + objs[0].handle = cmd_bo; + objs[0].relocation_count = 0; + objs[0].relocs_ptr = 0; + objs[0].alignment = 0; + objs[0].offset = 0; + objs[0].flags = 0; + objs[0].rsvd1 = 0; + objs[0].rsvd2 = 0; + + execbuf.buffers_ptr = (uintptr_t)objs; + execbuf.buffer_count = 1; + execbuf.batch_start_offset = 0; + execbuf.batch_len = size; + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = ring; + i915_execbuffer2_set_context_id(execbuf, 0); + execbuf.rsvd2 = 0; + + ret = drmIoctl(fd, + DRM_IOCTL_I915_GEM_EXECBUFFER2, + &execbuf); + if (ret == 0) + igt_assert(expected_ret == 0); + else + igt_assert(-errno == expected_ret); + + gem_sync(fd, cmd_bo); + gem_close(fd, cmd_bo); + + return 1; +} + +uint32_t handle; +int fd; + +#define MI_ARB_ON_OFF (0x8 << 23) +#define MI_DISPLAY_FLIP ((0x14 << 23) | 1) +#define MI_LOAD_REGISTER_IMM ((0x22 << 23) | 1) + +#define GFX_OP_PIPE_CONTROL ((0x3<<29)|(0x3<<27)|(0x2<<24)|2) +#define PIPE_CONTROL_QW_WRITE (1<<14) +#define PIPE_CONTROL_LRI_POST_OP (1<<23) + +#define OACONTROL 0x2360 + +igt_main +{ + igt_fixture { + int parser_version = 0; + drm_i915_getparam_t gp; + int rc; + + fd = drm_open_any(); + + gp.param = I915_PARAM_CMD_PARSER_VERSION; + gp.value = &parser_version; + rc = drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp); + igt_require(!rc && parser_version > 0); + + handle = gem_create(fd, 4096); + + /* ATM cmd parser only exists on gen7. */ + igt_require(intel_gen(intel_get_drm_devid(fd)) == 7); + } + + igt_subtest("basic-allowed") { + uint32_t pc[] = { + GFX_OP_PIPE_CONTROL, + PIPE_CONTROL_QW_WRITE, + 0, // To be patched + 0x12000000, + 0, + MI_BATCH_BUFFER_END, + }; + igt_assert( + exec_batch_patched(fd, handle, + pc, sizeof(pc), + 8, // patch offset, + 0x12000000)); + } + + igt_subtest("basic-rejected") { + uint32_t arb_on_off[] = { + MI_ARB_ON_OFF, + MI_BATCH_BUFFER_END, + }; + uint32_t display_flip[] = { + MI_DISPLAY_FLIP, + 0, 0, 0, + MI_BATCH_BUFFER_END, + 0 + }; + igt_assert( + exec_batch(fd, handle, + arb_on_off, sizeof(arb_on_off), + I915_EXEC_RENDER, + -EINVAL)); + igt_assert( + exec_batch(fd, handle, + arb_on_off, sizeof(arb_on_off), + I915_EXEC_BSD, + -EINVAL)); + if (gem_has_vebox(fd)) { + igt_assert( + exec_batch(fd, handle, + arb_on_off, sizeof(arb_on_off), + I915_EXEC_VEBOX, + -EINVAL)); + } + igt_assert( + exec_batch(fd, handle, + display_flip, sizeof(display_flip), + I915_EXEC_BLT, + -EINVAL)); + } + + igt_subtest("registers") { + uint32_t lri_bad[] = { + MI_LOAD_REGISTER_IMM, + 0, // disallowed register address + 0x12000000, + MI_BATCH_BUFFER_END, + }; + uint32_t lri_ok[] = { + MI_LOAD_REGISTER_IMM, + 0x5280, // allowed register address (SO_WRITE_OFFSET[0]) + 0x1, + MI_BATCH_BUFFER_END, + }; + igt_assert( + exec_batch(fd, handle, + lri_bad, sizeof(lri_bad), + I915_EXEC_RENDER, + -EINVAL)); + igt_assert( + exec_batch(fd, handle, + lri_ok, sizeof(lri_ok), + I915_EXEC_RENDER, + 0)); + } + + igt_subtest("bitmasks") { + uint32_t pc[] = { + GFX_OP_PIPE_CONTROL, + (PIPE_CONTROL_QW_WRITE | + PIPE_CONTROL_LRI_POST_OP), + 0, // To be patched + 0x12000000, + 0, + MI_BATCH_BUFFER_END, + }; + igt_assert( + exec_batch(fd, handle, + pc, sizeof(pc), + I915_EXEC_RENDER, + -EINVAL)); + } + + igt_subtest("batch-without-end") { + uint32_t noop[1024] = { 0 }; + igt_assert( + exec_batch(fd, handle, + noop, sizeof(noop), + I915_EXEC_RENDER, + -EINVAL)); + } + + igt_subtest("cmd-crossing-page") { + uint32_t lri_ok[] = { + MI_LOAD_REGISTER_IMM, + 0x5280, // allowed register address (SO_WRITE_OFFSET[0]) + 0x1, + MI_BATCH_BUFFER_END, + }; + igt_assert( + exec_split_batch(fd, + lri_ok, sizeof(lri_ok), + I915_EXEC_RENDER, + 0)); + } + + igt_subtest("oacontrol-tracking") { + uint32_t lri_ok[] = { + MI_LOAD_REGISTER_IMM, + OACONTROL, + 0x31337000, + MI_LOAD_REGISTER_IMM, + OACONTROL, + 0x0, + MI_BATCH_BUFFER_END, + 0 + }; + uint32_t lri_bad[] = { + MI_LOAD_REGISTER_IMM, + OACONTROL, + 0x31337000, + MI_BATCH_BUFFER_END, + }; + uint32_t lri_extra_bad[] = { + MI_LOAD_REGISTER_IMM, + OACONTROL, + 0x31337000, + MI_LOAD_REGISTER_IMM, + OACONTROL, + 0x0, + MI_LOAD_REGISTER_IMM, + OACONTROL, + 0x31337000, + MI_BATCH_BUFFER_END, + }; + igt_assert( + exec_batch(fd, handle, + lri_ok, sizeof(lri_ok), + I915_EXEC_RENDER, + 0)); + igt_assert( + exec_batch(fd, handle, + lri_bad, sizeof(lri_bad), + I915_EXEC_RENDER, + -EINVAL)); + igt_assert( + exec_batch(fd, handle, + lri_extra_bad, sizeof(lri_extra_bad), + I915_EXEC_RENDER, + -EINVAL)); + } + + igt_fixture { + gem_close(fd, handle); + + close(fd); + } +} diff --git a/tests/gem_fd_exhaustion.c b/tests/gem_fd_exhaustion.c new file mode 100644 index 00000000..8ba631f6 --- /dev/null +++ b/tests/gem_fd_exhaustion.c @@ -0,0 +1,94 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Daniel Vetter <daniel.vetter@ffwll.ch> + * + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/resource.h> +#include <sys/time.h> +#include <fcntl.h> +#include <limits.h> + +#include "drmtest.h" +#include "ioctl_wrappers.h" +#include "igt_aux.h" + + +#define FD_ARR_SZ 100 +int fd_arr[FD_ARR_SZ]; + +igt_simple_main +{ + int fd, i; + struct rlimit rlim; + unsigned nofile_rlim; + FILE *file_max = fopen("/proc/sys/fs/file-max", "r"); + igt_assert(fscanf(file_max, "%u", &nofile_rlim) == 1); + fclose(file_max); + + igt_info("System limit for open files is %u\n", nofile_rlim); + + igt_assert(getrlimit(RLIMIT_NOFILE, &rlim) == 0); + rlim.rlim_cur = nofile_rlim; + rlim.rlim_max = nofile_rlim; + igt_assert(setrlimit(RLIMIT_NOFILE, &rlim) == 0); + + fd = drm_open_any(); + + igt_assert(open("/dev/null", O_RDONLY) >= 0); + + igt_fork(n, 1) { + igt_drop_root(); + + for (i = 0; ; i++) { + int tmp_fd = open("/dev/null", O_RDONLY); + uint32_t handle; + + if (tmp_fd >= 0 && i < FD_ARR_SZ) + fd_arr[i] = tmp_fd; + + handle = __gem_create(fd, 4096); + if (handle) + gem_close(fd, handle); + + + if (tmp_fd < 0) { + /* Ensure we actually hit the failure path ... */ + igt_assert(handle == 0); + igt_info("fd exhaustion after %i rounds.\n", i); + break; + } + } + + /* The child will free all the fds when exiting, so no need to + * clean up to mess to ensure that the parent can at least run + * the exit handlers. */ + } + + igt_waitchildren(); + + close(fd); +} diff --git a/tests/gem_fence_thrash.c b/tests/gem_fence_thrash.c index 3d50e334..84b0f555 100644 --- a/tests/gem_fence_thrash.c +++ b/tests/gem_fence_thrash.c @@ -26,22 +26,22 @@ * */ +#ifdef HAVE_CONFIG_H #include "config.h" +#endif #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/ioctl.h> -#include <sys/mman.h> #include <pthread.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #define OBJECT_SIZE (128*1024) /* restricted to 1MiB alignment on i915 fences */ @@ -53,17 +53,30 @@ * when copying between two buffers and thus constantly swapping fences. */ +struct test { + int fd; + int tiling; + int num_surfaces; +}; + static void * -bo_create (int fd) +bo_create (int fd, int tiling) { void *ptr; int handle; handle = gem_create(fd, OBJECT_SIZE); - gem_set_tiling(fd, handle, I915_TILING_X, 1024); + /* dirty cpu caches a bit ... */ + ptr = gem_mmap__cpu(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE); + igt_assert(ptr); + memset(ptr, 0, OBJECT_SIZE); + munmap(ptr, OBJECT_SIZE); + + gem_set_tiling(fd, handle, tiling, 1024); ptr = gem_mmap(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE); + igt_assert(ptr); /* XXX: mmap_gtt pulls the bo into the GTT read domain. */ gem_sync(fd, handle); @@ -74,12 +87,13 @@ bo_create (int fd) static void * bo_copy (void *_arg) { - int fd = *(int *)_arg; + struct test *t = (struct test *)_arg; + int fd = t->fd; int n; char *a, *b; - a = bo_create (fd); - b = bo_create (fd); + a = bo_create (fd, t->tiling); + b = bo_create (fd, t->tiling); for (n = 0; n < 1000; n++) { memcpy (a, b, OBJECT_SIZE); @@ -89,31 +103,131 @@ bo_copy (void *_arg) return NULL; } -int -main(int argc, char **argv) +static void +_bo_write_verify(struct test *t) +{ + int fd = t->fd; + int i, k; + uint32_t **s; + uint32_t v; + unsigned int dwords = OBJECT_SIZE >> 2; + const char *tile_str[] = { "none", "x", "y" }; + + igt_assert(t->tiling >= 0 && t->tiling <= I915_TILING_Y); + igt_assert(t->num_surfaces > 0); + + s = calloc(sizeof(*s), t->num_surfaces); + igt_assert(s); + + for (k = 0; k < t->num_surfaces; k++) + s[k] = bo_create(fd, t->tiling); + + for (k = 0; k < t->num_surfaces; k++) { + volatile uint32_t *a = s[k]; + + for (i = 0; i < dwords; i++) { + a[i] = i; + v = a[i]; + igt_assert_f(v == i, + "tiling %s: write failed at %d (%x)\n", + tile_str[t->tiling], i, v); + } + + for (i = 0; i < dwords; i++) { + v = a[i]; + igt_assert_f(v == i, + "tiling %s: verify failed at %d (%x)\n", + tile_str[t->tiling], i, v); + } + } + + for (k = 0; k < t->num_surfaces; k++) + munmap(s[k], OBJECT_SIZE); + + free(s); +} + +static void * +bo_write_verify(void *_arg) +{ + struct test *t = (struct test *)_arg; + int i; + + for (i = 0; i < 10; i++) + _bo_write_verify(t); + + return 0; +} + +static int run_test(int threads_per_fence, void *f, int tiling, + int surfaces_per_thread) { - drm_i915_getparam_t gp; - pthread_t threads[32]; - int n, num_fences; - int fd, ret; + struct test t; + pthread_t *threads; + int n, num_fences, num_threads; - fd = drm_open_any(); + t.fd = drm_open_any(); + t.tiling = tiling; + t.num_surfaces = surfaces_per_thread; - gp.param = I915_PARAM_NUM_FENCES_AVAIL; - gp.value = &num_fences; - ret = ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp); - assert (ret == 0); + num_fences = gem_available_fences(t.fd); + igt_assert(num_fences > 0); - printf ("creating %d threads\n", num_fences); - assert (num_fences < sizeof (threads) / sizeof (threads[0])); + num_threads = threads_per_fence * num_fences; - for (n = 0; n < num_fences; n++) - pthread_create (&threads[n], NULL, bo_copy, &fd); + igt_info("%s: threads %d, fences %d, tiling %d, surfaces per thread %d\n", + f == bo_copy ? "copy" : "write-verify", num_threads, + num_fences, tiling, surfaces_per_thread); - for (n = 0; n < num_fences; n++) - pthread_join (threads[n], NULL); + if (threads_per_fence) { + threads = calloc(sizeof(*threads), num_threads); + igt_assert(threads != NULL); - close(fd); + for (n = 0; n < num_threads; n++) + pthread_create (&threads[n], NULL, f, &t); + + for (n = 0; n < num_threads; n++) + pthread_join (threads[n], NULL); + } else { + void *(*func)(void *) = f; + igt_assert(func(&t) == (void *)0); + } + + close(t.fd); return 0; } + +igt_main +{ + igt_skip_on_simulation(); + + igt_subtest("bo-write-verify-none") + igt_assert(run_test(0, bo_write_verify, I915_TILING_NONE, 80) == 0); + + igt_subtest("bo-write-verify-x") + igt_assert(run_test(0, bo_write_verify, I915_TILING_X, 80) == 0); + + igt_subtest("bo-write-verify-y") + igt_assert(run_test(0, bo_write_verify, I915_TILING_Y, 80) == 0); + + igt_subtest("bo-write-verify-threaded-none") + igt_assert(run_test(5, bo_write_verify, I915_TILING_NONE, 2) == 0); + + igt_subtest("bo-write-verify-threaded-x") { + igt_assert(run_test(2, bo_write_verify, I915_TILING_X, 2) == 0); + igt_assert(run_test(5, bo_write_verify, I915_TILING_X, 2) == 0); + igt_assert(run_test(10, bo_write_verify, I915_TILING_X, 2) == 0); + igt_assert(run_test(20, bo_write_verify, I915_TILING_X, 2) == 0); + } + + igt_subtest("bo-write-verify-threaded-y") { + igt_assert(run_test(2, bo_write_verify, I915_TILING_Y, 2) == 0); + igt_assert(run_test(5, bo_write_verify, I915_TILING_Y, 2) == 0); + igt_assert(run_test(10, bo_write_verify, I915_TILING_Y, 2) == 0); + igt_assert(run_test(20, bo_write_verify, I915_TILING_Y, 2) == 0); + } + + igt_subtest("bo-copy") + igt_assert(run_test(1, bo_copy, I915_TILING_X, 1) == 0); +} diff --git a/tests/gem_fenced_exec_thrash.c b/tests/gem_fenced_exec_thrash.c index 8281449e..42b7841d 100644 --- a/tests/gem_fenced_exec_thrash.c +++ b/tests/gem_fenced_exec_thrash.c @@ -31,13 +31,17 @@ #include <sys/ioctl.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> +#include <errno.h> + #include <drm.h> -#include <i915_drm.h> +#include "ioctl_wrappers.h" #include "drmtest.h" +#include "intel_chipset.h" +#include "intel_io.h" +#include "igt_aux.h" #define WIDTH 1024 #define HEIGHT 1024 @@ -45,9 +49,7 @@ #define BATCH_SIZE 4096 -#define MAX_FENCES 16 - -#define MI_BATCH_BUFFER_END (0xA<<23) +#define MAX_FENCES 32 /* * Testcase: execbuf fence accounting @@ -61,6 +63,55 @@ * each command. */ +static drm_intel_bufmgr *bufmgr; +struct intel_batchbuffer *batch; +uint32_t devid; + +static void emit_dummy_load(void) +{ + int i; + uint32_t tile_flags = 0; + uint32_t tiling_mode = I915_TILING_X; + unsigned long pitch; + drm_intel_bo *dummy_bo; + + dummy_bo = drm_intel_bo_alloc_tiled(bufmgr, "tiled dummy_bo", 2048, 2048, + 4, &tiling_mode, &pitch, 0); + + if (IS_965(devid)) { + pitch /= 4; + tile_flags = XY_SRC_COPY_BLT_SRC_TILED | + XY_SRC_COPY_BLT_DST_TILED; + } + + for (i = 0; i < 5; i++) { + BLIT_COPY_BATCH_START(devid, tile_flags); + OUT_BATCH((3 << 24) | /* 32 bits */ + (0xcc << 16) | /* copy ROP */ + pitch); + OUT_BATCH(0 << 16 | 1024); + OUT_BATCH((2048) << 16 | (2048)); + OUT_RELOC_FENCED(dummy_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(devid); + OUT_BATCH(0 << 16 | 0); + OUT_BATCH(pitch); + OUT_RELOC_FENCED(dummy_bo, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(devid); + ADVANCE_BATCH(); + + if (IS_GEN6(devid) || IS_GEN7(devid)) { + BEGIN_BATCH(3); + OUT_BATCH(XY_SETUP_CLIP_BLT_CMD); + OUT_BATCH(0); + OUT_BATCH(0); + ADVANCE_BATCH(); + } + } + intel_batchbuffer_flush(batch); + + drm_intel_bo_unreference(dummy_bo); +} + static uint32_t tiled_bo_create (int fd) { @@ -86,22 +137,6 @@ batch_create (int fd) return batch_handle; } -static int get_num_fences(int fd) -{ - drm_i915_getparam_t gp; - int ret, val; - - gp.param = I915_PARAM_NUM_FENCES_AVAIL; - gp.value = &val; - ret = drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp); - assert (ret == 0); - - printf ("total %d fences\n", val); - assert(val > 4); - - return val - 2; -} - static void fill_reloc(struct drm_i915_gem_relocation_entry *reloc, uint32_t handle) { reloc->offset = 2 * sizeof(uint32_t); @@ -110,23 +145,34 @@ static void fill_reloc(struct drm_i915_gem_relocation_entry *reloc, uint32_t han reloc->write_domain = 0; } -int -main(int argc, char **argv) +#define BUSY_LOAD (1 << 0) +#define INTERRUPTIBLE (1 << 1) + +static void run_test(int fd, int num_fences, int expected_errno, + unsigned flags) { struct drm_i915_gem_execbuffer2 execbuf[2]; - struct drm_i915_gem_exec_object2 exec[2][2*MAX_FENCES+1]; - struct drm_i915_gem_relocation_entry reloc[2*MAX_FENCES]; + struct drm_i915_gem_exec_object2 exec[2][2*MAX_FENCES+3]; + struct drm_i915_gem_relocation_entry reloc[2*MAX_FENCES+2]; - int fd = drm_open_any(); - int i, n, num_fences; + int i, n; int loop = 1000; + if (flags & BUSY_LOAD) { + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + batch = intel_batchbuffer_alloc(bufmgr, devid); + + /* Takes forever otherwise. */ + loop = 50; + } + + if (flags & INTERRUPTIBLE) + igt_fork_signal_helper(); + memset(execbuf, 0, sizeof(execbuf)); memset(exec, 0, sizeof(exec)); memset(reloc, 0, sizeof(reloc)); - num_fences = get_num_fences(fd) & ~1; - assert(num_fences <= MAX_FENCES); for (n = 0; n < 2*num_fences; n++) { uint32_t handle = tiled_bo_create(fd); exec[1][2*num_fences - n-1].handle = exec[0][n].handle = handle; @@ -149,18 +195,55 @@ main(int argc, char **argv) do { int ret; + if (flags & BUSY_LOAD) + emit_dummy_load(); + ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf[0]); - assert(ret == 0); + igt_assert(expected_errno ? + ret < 0 && errno == expected_errno : + ret == 0); ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf[1]); - assert(ret == 0); + igt_assert(expected_errno ? + ret < 0 && errno == expected_errno : + ret == 0); } while (--loop); - close(fd); + if (flags & INTERRUPTIBLE) + igt_stop_signal_helper(); +} + +int fd; +int num_fences; + +igt_main +{ + igt_skip_on_simulation(); + + igt_fixture { + fd = drm_open_any(); + num_fences = gem_available_fences(fd); + igt_assert(num_fences > 4); + devid = intel_get_drm_devid(fd); + + igt_assert(num_fences <= MAX_FENCES); + } + + igt_subtest("2-spare-fences") + run_test(fd, num_fences - 2, 0, 0); + for (unsigned flags = 0; flags < 4; flags++) { + igt_subtest_f("no-spare-fences%s%s", + flags & BUSY_LOAD ? "-busy" : "", + flags & INTERRUPTIBLE ? "-interruptible" : "") + run_test(fd, num_fences, 0, flags); + } + igt_subtest("too-many-fences") + run_test(fd, num_fences + 1, intel_gen(devid) >= 4 ? 0 : EDEADLK, 0); - return 0; + igt_fixture + close(fd); } diff --git a/tests/gem_flink.c b/tests/gem_flink.c index c8694808..627a6778 100644 --- a/tests/gem_flink.c +++ b/tests/gem_flink.c @@ -28,14 +28,13 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/ioctl.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" static void @@ -43,24 +42,24 @@ test_flink(int fd) { struct drm_i915_gem_create create; struct drm_gem_flink flink; - struct drm_gem_open gem_open; + struct drm_gem_open open_struct; int ret; - printf("Testing flink and open.\n"); + igt_info("Testing flink and open.\n"); memset(&create, 0, sizeof(create)); create.size = 16 * 1024; ret = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create); - assert(ret == 0); + igt_assert(ret == 0); flink.handle = create.handle; ret = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink); - assert(ret == 0); + igt_assert(ret == 0); - gem_open.name = flink.name; - ret = ioctl(fd, DRM_IOCTL_GEM_OPEN, &gem_open); - assert(ret == 0); - assert(gem_open.handle != 0); + open_struct.name = flink.name; + ret = ioctl(fd, DRM_IOCTL_GEM_OPEN, &open_struct); + igt_assert(ret == 0); + igt_assert(open_struct.handle != 0); } static void @@ -71,21 +70,21 @@ test_double_flink(int fd) struct drm_gem_flink flink2; int ret; - printf("Testing repeated flink.\n"); + igt_info("Testing repeated flink.\n"); memset(&create, 0, sizeof(create)); create.size = 16 * 1024; ret = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create); - assert(ret == 0); + igt_assert(ret == 0); flink.handle = create.handle; ret = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink); - assert(ret == 0); + igt_assert(ret == 0); flink2.handle = create.handle; ret = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink2); - assert(ret == 0); - assert(flink2.name == flink.name); + igt_assert(ret == 0); + igt_assert(flink2.name == flink.name); } static void @@ -94,37 +93,77 @@ test_bad_flink(int fd) struct drm_gem_flink flink; int ret; - printf("Testing error return on bad flink ioctl.\n"); + igt_info("Testing error return on bad flink ioctl.\n"); flink.handle = 0x10101010; ret = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink); - assert(ret == -1 && errno == ENOENT); + igt_assert(ret == -1 && errno == ENOENT); } static void test_bad_open(int fd) { - struct drm_gem_open gem_open; + struct drm_gem_open open_struct; int ret; - printf("Testing error return on bad open ioctl.\n"); + igt_info("Testing error return on bad open ioctl.\n"); - gem_open.name = 0x10101010; - ret = ioctl(fd, DRM_IOCTL_GEM_OPEN, &gem_open); + open_struct.name = 0x10101010; + ret = ioctl(fd, DRM_IOCTL_GEM_OPEN, &open_struct); - assert(ret == -1 && errno == ENOENT); + igt_assert(ret == -1 && errno == ENOENT); } -int main(int argc, char **argv) +static void +test_flink_lifetime(int fd) { - int fd; + struct drm_i915_gem_create create; + struct drm_gem_flink flink; + struct drm_gem_open open_struct; + int ret, fd2; + + igt_info("Testing flink lifetime.\n"); + + fd2 = drm_open_any(); + + memset(&create, 0, sizeof(create)); + create.size = 16 * 1024; + ret = ioctl(fd2, DRM_IOCTL_I915_GEM_CREATE, &create); + igt_assert(ret == 0); + + flink.handle = create.handle; + ret = ioctl(fd2, DRM_IOCTL_GEM_FLINK, &flink); + igt_assert(ret == 0); - fd = drm_open_any(); + open_struct.name = flink.name; + ret = ioctl(fd, DRM_IOCTL_GEM_OPEN, &open_struct); + igt_assert(ret == 0); + igt_assert(open_struct.handle != 0); - test_flink(fd); - test_double_flink(fd); - test_bad_flink(fd); - test_bad_open(fd); + close(fd2); + fd2 = drm_open_any(); - return 0; + open_struct.name = flink.name; + ret = ioctl(fd2, DRM_IOCTL_GEM_OPEN, &open_struct); + igt_assert(ret == 0); + igt_assert(open_struct.handle != 0); +} + +int fd; + +igt_main +{ + igt_fixture + fd = drm_open_any(); + + igt_subtest("basic") + test_flink(fd); + igt_subtest("double-flink") + test_double_flink(fd); + igt_subtest("bad-flink") + test_bad_flink(fd); + igt_subtest("bad-open") + test_bad_open(fd); + igt_subtest("flink-lifetime") + test_flink_lifetime(fd); } diff --git a/tests/gem_flink_race.c b/tests/gem_flink_race.c new file mode 100644 index 00000000..eab5ef2a --- /dev/null +++ b/tests/gem_flink_race.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Daniel Vetter <daniel.vetter@ffwll.ch> + */ + +#define _GNU_SOURCE +#include <sys/ioctl.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <pthread.h> +#include <errno.h> + +#include "drmtest.h" +#include "ioctl_wrappers.h" +#include "intel_bufmgr.h" +#include "igt_debugfs.h" + +/* Testcase: check for flink/open vs. gem close races + * + * The gem flink open ioctl had a little race with gem close which could result + * in the flink name and corresponding reference getting leaked. + */ + +/* We want lockless and I'm to lazy to dig out an atomic libarary. On x86 this + * works, too. */ +volatile int pls_die = 0; +int fd; + +static int get_object_count(void) +{ + FILE *file; + int ret, scanned; + int device = drm_get_card(); + char *path; + + igt_drop_caches_set(DROP_RETIRE); + + ret = asprintf(&path, "/sys/kernel/debug/dri/%d/i915_gem_objects", device); + igt_assert(ret != -1); + + file = fopen(path, "r"); + + scanned = fscanf(file, "%i objects", &ret); + igt_assert(scanned == 1); + + return ret; +} + + +static void *thread_fn_flink_name(void *p) +{ + struct drm_gem_open open_struct; + int ret; + + while (!pls_die) { + memset(&open_struct, 0, sizeof(open_struct)); + + open_struct.name = 1; + ret = ioctl(fd, DRM_IOCTL_GEM_OPEN, &open_struct); + if (ret == 0) { + uint32_t name = gem_flink(fd, open_struct.handle); + + igt_assert(name == 1); + + gem_close(fd, open_struct.handle); + } else + igt_assert(errno == ENOENT); + } + + return (void *)0; +} + +static void test_flink_name(void) +{ + pthread_t *threads; + int r, i, num_threads; + void *status; + + num_threads = sysconf(_SC_NPROCESSORS_ONLN) - 1; + if (!num_threads) + num_threads = 1; + + threads = calloc(num_threads, sizeof(pthread_t)); + + fd = drm_open_any(); + igt_assert(fd >= 0); + + for (i = 0; i < num_threads; i++) { + r = pthread_create(&threads[i], NULL, + thread_fn_flink_name, NULL); + igt_assert(r == 0); + } + + for (i = 0; i < 1000000; i++) { + uint32_t handle; + + handle = gem_create(fd, 4096); + + gem_flink(fd, handle); + + gem_close(fd, handle); + } + + pls_die = 1; + + for (i = 0; i < num_threads; i++) { + pthread_join(threads[i], &status); + igt_assert(status == 0); + } + + close(fd); +} + +static void *thread_fn_flink_close(void *p) +{ + struct drm_gem_flink flink; + struct drm_gem_close close_bo; + uint32_t handle; + + while (!pls_die) { + /* We want to race gem close against flink on handle one.*/ + handle = gem_create(fd, 4096); + if (handle != 1) + gem_close(fd, handle); + + /* raw ioctl since we expect this to fail */ + flink.handle = 1; + ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink); + + close_bo.handle = 1; + ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close_bo); + } + + return (void *)0; +} + +static void test_flink_close(void) +{ + pthread_t *threads; + int r, i, num_threads; + int obj_count; + void *status; + int fake; + + /* Allocate exit handler fds in here so that we dont screw + * up the counts */ + fake = drm_open_any(); + + obj_count = get_object_count(); + + num_threads = sysconf(_SC_NPROCESSORS_ONLN); + + threads = calloc(num_threads, sizeof(pthread_t)); + + fd = drm_open_any(); + igt_assert(fd >= 0); + + for (i = 0; i < num_threads; i++) { + r = pthread_create(&threads[i], NULL, + thread_fn_flink_close, NULL); + igt_assert(r == 0); + } + + sleep(5); + + pls_die = 1; + + for (i = 0; i < num_threads; i++) { + pthread_join(threads[i], &status); + igt_assert(status == 0); + } + + close(fd); + + obj_count = get_object_count() - obj_count; + + igt_info("leaked %i objects\n", obj_count); + + close(fake); + + igt_assert(obj_count == 0); +} + +igt_main +{ + igt_skip_on_simulation(); + + igt_subtest("flink_name") + test_flink_name(); + + igt_subtest("flink_close") + test_flink_close(); +} diff --git a/tests/gem_gtt_concurrent_blit.c b/tests/gem_gtt_concurrent_blit.c deleted file mode 100644 index c68af7b5..00000000 --- a/tests/gem_gtt_concurrent_blit.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright © 2009,2012 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * Authors: - * Eric Anholt <eric@anholt.net> - * Chris Wilson <chris@chris-wilson.co.uk> - * - */ - -/** @file gem_cpu_concurrent_blit.c - * - * This is a test of GTT mmap read/write behavior when writing to active - * buffers. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <assert.h> -#include <fcntl.h> -#include <inttypes.h> -#include <errno.h> -#include <sys/stat.h> -#include <sys/time.h> -#include "drm.h" -#include "i915_drm.h" -#include "drmtest.h" -#include "intel_bufmgr.h" -#include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" - -static void -set_bo(drm_intel_bo *bo, uint32_t val, int width, int height) -{ - int size = width * height; - uint32_t *vaddr; - - drm_intel_gem_bo_start_gtt_access(bo, true); - vaddr = bo->virtual; - while (size--) - *vaddr++ = val; -} - -static void -cmp_bo(drm_intel_bo *bo, uint32_t val, int width, int height) -{ - int size = width * height; - uint32_t *vaddr; - - drm_intel_gem_bo_start_gtt_access(bo, false); - vaddr = bo->virtual; - while (size--) - assert(*vaddr++ == val); -} - -static drm_intel_bo * -create_bo(drm_intel_bufmgr *bufmgr, uint32_t val, int width, int height) -{ - drm_intel_bo *bo; - - bo = drm_intel_bo_alloc(bufmgr, "bo", 4*width*height, 0); - assert(bo); - - /* gtt map doesn't have a write parameter, so just keep the mapping - * around (to avoid the set_domain with the gtt write domain set) and - * manually tell the kernel when we start access the gtt. */ - drm_intel_gem_bo_map_gtt(bo); - - set_bo(bo, val, width, height); - - return bo; -} - -int -main(int argc, char **argv) -{ - drm_intel_bufmgr *bufmgr; - struct intel_batchbuffer *batch; - int num_buffers = 128, max; - drm_intel_bo *src[128], *dst[128], *dummy; - int width = 512, height = 512; - int fd; - int i; - - fd = drm_open_any(); - - max = gem_aperture_size (fd) / (1024 * 1024) / 2; - if (num_buffers > max) - num_buffers = max; - - bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - drm_intel_bufmgr_gem_enable_reuse(bufmgr); - batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); - - for (i = 0; i < num_buffers; i++) { - src[i] = create_bo(bufmgr, i, width, height); - dst[i] = create_bo(bufmgr, ~i, width, height); - } - dummy = create_bo(bufmgr, 0, width, height); - - /* try to overwrite the source values */ - for (i = 0; i < num_buffers; i++) - intel_copy_bo(batch, dst[i], src[i], width, height); - for (i = num_buffers; i--; ) - set_bo(src[i], 0xdeadbeef, width, height); - for (i = 0; i < num_buffers; i++) - cmp_bo(dst[i], i, width, height); - - /* try to read the results before the copy completes */ - for (i = 0; i < num_buffers; i++) - intel_copy_bo(batch, dst[i], src[i], width, height); - for (i = num_buffers; i--; ) - cmp_bo(dst[i], 0xdeadbeef, width, height); - - /* and finally try to trick the kernel into loosing the pending write */ - for (i = num_buffers; i--; ) - set_bo(src[i], 0xabcdabcd, width, height); - for (i = 0; i < num_buffers; i++) - intel_copy_bo(batch, dst[i], src[i], width, height); - for (i = num_buffers; i--; ) - intel_copy_bo(batch, dummy, dst[i], width, height); - for (i = num_buffers; i--; ) - cmp_bo(dst[i], 0xabcdabcd, width, height); - - return 0; -} diff --git a/tests/gem_gtt_cpu_tlb.c b/tests/gem_gtt_cpu_tlb.c index 68533709..953070c0 100644 --- a/tests/gem_gtt_cpu_tlb.c +++ b/tests/gem_gtt_cpu_tlb.c @@ -33,18 +33,16 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include <sys/ioctl.h> -#include <sys/mman.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" #define OBJ_SIZE (1024*1024) @@ -68,8 +66,7 @@ create_bo(int fd) return handle; } -int -main(int argc, char **argv) +igt_simple_main { int fd; int i; @@ -77,6 +74,8 @@ main(int argc, char **argv) uint32_t *ptr; + igt_skip_on_simulation(); + fd = drm_open_any(); handle = gem_create(fd, OBJ_SIZE); @@ -90,7 +89,7 @@ main(int argc, char **argv) /* stirr up the page allocator a bit. */ ptr = malloc(OBJ_SIZE); - assert(ptr); + igt_assert(ptr); memset(ptr, 0x1, OBJ_SIZE); handle = create_bo(fd); @@ -100,9 +99,7 @@ main(int argc, char **argv) */ gem_read(fd, handle, 0, ptr, OBJ_SIZE); for (i = 0; i < OBJ_SIZE/4; i++) - assert(ptr[i] == i); + igt_assert(ptr[i] == i); close(fd); - - return 0; } diff --git a/tests/gem_gtt_hog.c b/tests/gem_gtt_hog.c new file mode 100644 index 00000000..5d475400 --- /dev/null +++ b/tests/gem_gtt_hog.c @@ -0,0 +1,192 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Chris Wilson <chris@chris-wilson.co.uk> + * + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/wait.h> + +#include "drm.h" +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_chipset.h" + +static const uint32_t canary = 0xdeadbeef; + +typedef struct data { + int fd; + int devid; + int intel_gen; +} data_t; + +static double elapsed(const struct timeval *start, + const struct timeval *end) +{ + return 1e6*(end->tv_sec - start->tv_sec) + (end->tv_usec - start->tv_usec); +} + +static void busy(data_t *data, uint32_t handle, int size, int loops) +{ + struct drm_i915_gem_relocation_entry reloc[20]; + struct drm_i915_gem_exec_object2 gem_exec[2]; + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_pwrite gem_pwrite; + struct drm_i915_gem_create create; + uint32_t buf[170], *b; + int i; + + memset(reloc, 0, sizeof(reloc)); + memset(gem_exec, 0, sizeof(gem_exec)); + memset(&execbuf, 0, sizeof(execbuf)); + + b = buf; + for (i = 0; i < 20; i++) { + *b++ = XY_COLOR_BLT_CMD_NOLEN | + ((data->intel_gen >= 8) ? 5 : 4) | + COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB; + *b++ = 0xf0 << 16 | 1 << 25 | 1 << 24 | 4096; + *b++ = 0; + *b++ = size >> 12 << 16 | 1024; + reloc[i].offset = (b - buf) * sizeof(uint32_t); + reloc[i].target_handle = handle; + reloc[i].read_domains = I915_GEM_DOMAIN_RENDER; + reloc[i].write_domain = I915_GEM_DOMAIN_RENDER; + *b++ = 0; + if (data->intel_gen >= 8) + *b++ = 0; + *b++ = canary; + } + *b++ = MI_BATCH_BUFFER_END; + if ((b - buf) & 1) + *b++ = 0; + + gem_exec[0].handle = handle; + gem_exec[0].flags = EXEC_OBJECT_NEEDS_FENCE; + + create.handle = 0; + create.size = 4096; + drmIoctl(data->fd, DRM_IOCTL_I915_GEM_CREATE, &create); + gem_exec[1].handle = create.handle; + gem_exec[1].relocation_count = 20; + gem_exec[1].relocs_ptr = (uintptr_t)reloc; + + execbuf.buffers_ptr = (uintptr_t)gem_exec; + execbuf.buffer_count = 2; + execbuf.batch_len = (b - buf) * sizeof(buf[0]); + execbuf.flags = 1 << 11; + if (HAS_BLT_RING(data->devid)) + execbuf.flags |= I915_EXEC_BLT; + + gem_pwrite.handle = gem_exec[1].handle; + gem_pwrite.offset = 0; + gem_pwrite.size = execbuf.batch_len; + gem_pwrite.data_ptr = (uintptr_t)buf; + if (drmIoctl(data->fd, DRM_IOCTL_I915_GEM_PWRITE, &gem_pwrite) == 0) { + while (loops--) + drmIoctl(data->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + } + + drmIoctl(data->fd, DRM_IOCTL_GEM_CLOSE, &create.handle); +} + +static void run(data_t *data, int child) +{ + const int size = 4096 * (256 + child * child); + const int tiling = child % 2; + const int write = child % 2; + uint32_t handle = gem_create(data->fd, size); + uint32_t *ptr; + uint32_t x; + + igt_assert(handle); + + if (tiling != I915_TILING_NONE) + gem_set_tiling(data->fd, handle, tiling, 4096); + + /* load up the unfaulted bo */ + busy(data, handle, size, 100); + + /* Note that we ignore the API and rely on the implict + * set-to-gtt-domain within the fault handler. + */ + if (write) { + ptr = gem_mmap(data->fd, handle, size, PROT_READ | PROT_WRITE); + ptr[rand() % (size / 4)] = canary; + } else + ptr = gem_mmap(data->fd, handle, size, PROT_READ); + x = ptr[rand() % (size / 4)]; + munmap(ptr, size); + + igt_assert(x == canary); + exit(0); +} + +igt_simple_main +{ + struct timeval start, end; + pid_t children[64]; + data_t data = {}; + int n; + + /* check for an intel gpu before goint nuts. */ + int fd = drm_open_any(); + close(fd); + + igt_skip_on_simulation(); + + data.fd = drm_open_any(); + data.devid = intel_get_drm_devid(data.fd); + data.intel_gen = intel_gen(data.devid); + + gettimeofday(&start, NULL); + for (n = 0; n < ARRAY_SIZE(children); n++) { + switch ((children[n] = fork())) { + case -1: igt_assert(0); + case 0: run(&data, n); break; + default: break; + } + } + + for (n = 0; n < ARRAY_SIZE(children); n++) { + int status = -1; + while (waitpid(children[n], &status, 0) == -1 && + errno == -EINTR) + ; + igt_assert(status == 0); + } + gettimeofday(&end, NULL); + igt_info("Time to execute %lu children: %7.3fms\n", + ARRAY_SIZE(children), elapsed(&start, &end) / 1000); +} diff --git a/tests/gem_gtt_speed.c b/tests/gem_gtt_speed.c index 73a3c6dc..385eeb73 100644 --- a/tests/gem_gtt_speed.c +++ b/tests/gem_gtt_speed.c @@ -31,16 +31,14 @@ #include <stdint.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/ioctl.h> -#include <sys/mman.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #define OBJECT_SIZE 16384 @@ -61,10 +59,14 @@ int main(int argc, char **argv) int loop, i, tiling; int fd; + igt_simple_init(); + + igt_skip_on_simulation(); + if (argc > 1) size = atoi(argv[1]); if (size == 0) { - fprintf(stderr, "Invalid object size specified\n"); + igt_warn("Invalid object size specified\n"); return 1; } @@ -73,12 +75,12 @@ int main(int argc, char **argv) fd = drm_open_any(); handle = gem_create(fd, size); - assert(handle); + igt_assert(handle); for (tiling = I915_TILING_NONE; tiling <= I915_TILING_Y; tiling++) { if (tiling != I915_TILING_NONE) { - printf("\nSetting tiling mode to %s\n", - tiling == I915_TILING_X ? "X" : "Y"); + igt_info("\nSetting tiling mode to %s\n", + tiling == I915_TILING_X ? "X" : "Y"); gem_set_tiling(fd, handle, tiling, 512); } @@ -116,8 +118,8 @@ int main(int argc, char **argv) munmap(base, size); } gettimeofday(&end, NULL); - printf("Time to read %dk through a CPU map: %7.3fµs\n", - size/1024, elapsed(&start, &end, loop)); + igt_info("Time to read %dk through a CPU map: %7.3fµs\n", + size/1024, elapsed(&start, &end, loop)); /* mmap write */ gettimeofday(&start, NULL); @@ -131,8 +133,27 @@ int main(int argc, char **argv) munmap(base, size); } gettimeofday(&end, NULL); - printf("Time to write %dk through a CPU map: %7.3fµs\n", - size/1024, elapsed(&start, &end, loop)); + igt_info("Time to write %dk through a CPU map: %7.3fµs\n", + size/1024, elapsed(&start, &end, loop)); + + gettimeofday(&start, NULL); + for (loop = 0; loop < 1000; loop++) { + base = gem_mmap__cpu(fd, handle, size, PROT_READ | PROT_WRITE); + memset(base, 0, size); + munmap(base, size); + } + gettimeofday(&end, NULL); + igt_info("Time to clear %dk through a CPU map: %7.3fµs\n", + size/1024, elapsed(&start, &end, loop)); + + gettimeofday(&start, NULL); + base = gem_mmap__cpu(fd, handle, size, PROT_READ | PROT_WRITE); + for (loop = 0; loop < 1000; loop++) + memset(base, 0, size); + munmap(base, size); + gettimeofday(&end, NULL); + igt_info("Time to clear %dk through a cached CPU map: %7.3fµs\n", + size/1024, elapsed(&start, &end, loop)); } /* CPU pwrite */ @@ -140,16 +161,16 @@ int main(int argc, char **argv) for (loop = 0; loop < 1000; loop++) gem_write(fd, handle, 0, buf, size); gettimeofday(&end, NULL); - printf("Time to pwrite %dk through the CPU: %7.3fµs\n", - size/1024, elapsed(&start, &end, loop)); + igt_info("Time to pwrite %dk through the CPU: %7.3fµs\n", + size/1024, elapsed(&start, &end, loop)); /* CPU pread */ gettimeofday(&start, NULL); for (loop = 0; loop < 1000; loop++) gem_read(fd, handle, 0, buf, size); gettimeofday(&end, NULL); - printf("Time to pread %dk through the CPU: %7.3fµs\n", - size/1024, elapsed(&start, &end, loop)); + igt_info("Time to pread %dk through the CPU: %7.3fµs\n", + size/1024, elapsed(&start, &end, loop)); } /* prefault into gtt */ @@ -182,8 +203,8 @@ int main(int argc, char **argv) munmap(base, size); } gettimeofday(&end, NULL); - printf("Time to read %dk through a GTT map: %7.3fµs\n", - size/1024, elapsed(&start, &end, loop)); + igt_info("Time to read %dk through a GTT map: %7.3fµs\n", + size/1024, elapsed(&start, &end, loop)); /* mmap write */ gettimeofday(&start, NULL); @@ -197,8 +218,28 @@ int main(int argc, char **argv) munmap(base, size); } gettimeofday(&end, NULL); - printf("Time to write %dk through a GTT map: %7.3fµs\n", - size/1024, elapsed(&start, &end, loop)); + igt_info("Time to write %dk through a GTT map: %7.3fµs\n", + size/1024, elapsed(&start, &end, loop)); + + /* mmap clear */ + gettimeofday(&start, NULL); + for (loop = 0; loop < 1000; loop++) { + uint32_t *base = gem_mmap(fd, handle, size, PROT_READ | PROT_WRITE); + memset(base, 0, size); + munmap(base, size); + } + gettimeofday(&end, NULL); + igt_info("Time to clear %dk through a GTT map: %7.3fµs\n", + size/1024, elapsed(&start, &end, loop)); + + gettimeofday(&start, NULL);{ + uint32_t *base = gem_mmap(fd, handle, size, PROT_READ | PROT_WRITE); + for (loop = 0; loop < 1000; loop++) + memset(base, 0, size); + munmap(base, size); + } gettimeofday(&end, NULL); + igt_info("Time to clear %dk through a cached GTT map: %7.3fµs\n", + size/1024, elapsed(&start, &end, loop)); /* mmap read */ gettimeofday(&start, NULL); @@ -216,8 +257,8 @@ int main(int argc, char **argv) munmap(base, size); } gettimeofday(&end, NULL); - printf("Time to read %dk (again) through a GTT map: %7.3fµs\n", - size/1024, elapsed(&start, &end, loop)); + igt_info("Time to read %dk (again) through a GTT map: %7.3fµs\n", + size/1024, elapsed(&start, &end, loop)); if (tiling == I915_TILING_NONE) { /* GTT pwrite */ @@ -225,16 +266,16 @@ int main(int argc, char **argv) for (loop = 0; loop < 1000; loop++) gem_write(fd, handle, 0, buf, size); gettimeofday(&end, NULL); - printf("Time to pwrite %dk through the GTT: %7.3fµs\n", - size/1024, elapsed(&start, &end, loop)); + igt_info("Time to pwrite %dk through the GTT: %7.3fµs\n", + size/1024, elapsed(&start, &end, loop)); /* GTT pread */ gettimeofday(&start, NULL); for (loop = 0; loop < 1000; loop++) gem_read(fd, handle, 0, buf, size); gettimeofday(&end, NULL); - printf("Time to pread %dk through the GTT: %7.3fµs\n", - size/1024, elapsed(&start, &end, loop)); + igt_info("Time to pread %dk through the GTT: %7.3fµs\n", + size/1024, elapsed(&start, &end, loop)); /* GTT pwrite, including clflush */ gettimeofday(&start, NULL); @@ -243,8 +284,8 @@ int main(int argc, char **argv) gem_sync(fd, handle); } gettimeofday(&end, NULL); - printf("Time to pwrite %dk through the GTT (clflush): %7.3fµs\n", - size/1024, elapsed(&start, &end, loop)); + igt_info("Time to pwrite %dk through the GTT (clflush): %7.3fµs\n", + size/1024, elapsed(&start, &end, loop)); /* GTT pread, including clflush */ gettimeofday(&start, NULL); @@ -253,11 +294,11 @@ int main(int argc, char **argv) gem_read(fd, handle, 0, buf, size); } gettimeofday(&end, NULL); - printf("Time to pread %dk through the GTT (clflush): %7.3fµs\n", - size/1024, elapsed(&start, &end, loop)); + igt_info("Time to pread %dk through the GTT (clflush): %7.3fµs\n", + size/1024, elapsed(&start, &end, loop)); /* partial writes */ - printf("Now partial writes.\n"); + igt_info("Now partial writes.\n"); size /= 4; /* partial GTT pwrite, including clflush */ @@ -267,7 +308,7 @@ int main(int argc, char **argv) gem_sync(fd, handle); } gettimeofday(&end, NULL); - printf("Time to pwrite %dk through the GTT (clflush): %7.3fµs\n", + igt_info("Time to pwrite %dk through the GTT (clflush): %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); /* partial GTT pread, including clflush */ @@ -277,7 +318,7 @@ int main(int argc, char **argv) gem_read(fd, handle, 0, buf, size); } gettimeofday(&end, NULL); - printf("Time to pread %dk through the GTT (clflush): %7.3fµs\n", + igt_info("Time to pread %dk through the GTT (clflush): %7.3fµs\n", size/1024, elapsed(&start, &end, loop)); size *= 4; diff --git a/tests/gem_hang.c b/tests/gem_hang.c index f9db3400..8ebf6067 100644 --- a/tests/gem_hang.c +++ b/tests/gem_hang.c @@ -29,18 +29,18 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" +#include "intel_chipset.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; @@ -72,11 +72,9 @@ int main(int argc, char **argv) { int fd; - if (argc != 2) { - fprintf(stderr, "usage: %s <disabled pipe number>\n", - argv[0]); - exit(-1); - } + igt_assert_f(argc == 2, + "usage: %s <disabled pipe number>\n", + argv[0]); bad_pipe = atoi(argv[1]); diff --git a/tests/gem_hangcheck_forcewake.c b/tests/gem_hangcheck_forcewake.c index 96a30fef..cb8dd110 100644 --- a/tests/gem_hangcheck_forcewake.c +++ b/tests/gem_hangcheck_forcewake.c @@ -28,18 +28,18 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "intel_chipset.h" /* * Testcase: Provoke the hangcheck timer on an otherwise idle system @@ -58,13 +58,15 @@ struct intel_batchbuffer *batch; uint32_t blob[2048*2048]; #define MAX_BLT_SIZE 128 -int main(int argc, char **argv) +igt_simple_main { drm_intel_bo *bo = NULL; uint32_t tiling_mode = I915_TILING_X; unsigned long pitch, act_size; int fd, i, devid; + igt_skip_on_simulation(); + memset(blob, 'A', sizeof(blob)); fd = drm_open_any(); @@ -75,7 +77,7 @@ int main(int argc, char **argv) batch = intel_batchbuffer_alloc(bufmgr, devid); act_size = 2048; - printf("filling ring\n"); + igt_info("filling ring\n"); drm_intel_bo_unreference(bo); bo = drm_intel_bo_alloc_tiled(bufmgr, "tiled bo", act_size, act_size, 4, &tiling_mode, &pitch, 0); @@ -86,21 +88,20 @@ int main(int argc, char **argv) pitch /= 4; for (i = 0; i < 10000; i++) { - BEGIN_BATCH(8); - OUT_BATCH(XY_SRC_COPY_BLT_CMD | - XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB | - XY_SRC_COPY_BLT_SRC_TILED | - XY_SRC_COPY_BLT_DST_TILED); + BLIT_COPY_BATCH_START(devid, + XY_SRC_COPY_BLT_SRC_TILED | + XY_SRC_COPY_BLT_DST_TILED); OUT_BATCH((3 << 24) | /* 32 bits */ (0xcc << 16) | /* copy ROP */ pitch); OUT_BATCH(0 << 16 | 1024); OUT_BATCH((2048) << 16 | (2048)); OUT_RELOC_FENCED(bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(devid); OUT_BATCH(0 << 16 | 0); OUT_BATCH(pitch); OUT_RELOC_FENCED(bo, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(devid); ADVANCE_BATCH(); if (IS_GEN6(devid) || IS_GEN7(devid)) { @@ -112,16 +113,14 @@ int main(int argc, char **argv) } } - printf("waiting\n"); + igt_info("waiting\n"); sleep(10); - printf("done waiting, check dmesg\n"); + igt_info("done waiting, check dmesg\n"); drm_intel_bo_unreference(bo); intel_batchbuffer_free(batch); drm_intel_bufmgr_destroy(bufmgr); close(fd); - - return 0; } diff --git a/tests/gem_largeobject.c b/tests/gem_largeobject.c index 163bf101..0f929f8f 100644 --- a/tests/gem_largeobject.c +++ b/tests/gem_largeobject.c @@ -28,14 +28,13 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/ioctl.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" /* Should take 64 pages to store the page pointers on 64 bit */ @@ -49,7 +48,7 @@ test_large_object(int fd) struct drm_i915_gem_create create; struct drm_i915_gem_pin pin; uint32_t obj_size; - int ret; + char *ptr; memset(&create, 0, sizeof(create)); memset(&pin, 0, sizeof(pin)); @@ -61,35 +60,26 @@ test_large_object(int fd) else obj_size = OBJ_SIZE; create.size = obj_size; - printf("obj size %i\n", obj_size); + igt_info("obj size %i\n", obj_size); - ret = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create); - if (ret) { - fprintf(stderr, "object creation failed: %s\n", - strerror(errno)); - exit(ret); - } + igt_assert(ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create) == 0); - pin.handle = create.handle; - ret = ioctl(fd, DRM_IOCTL_I915_GEM_PIN, &pin); - if (ret) { - fprintf(stderr, "pin failed: %s\n", - strerror(errno)); - exit(ret); - } + /* prefault */ + ptr = gem_mmap__gtt(fd, create.handle, obj_size, PROT_WRITE | PROT_READ); + *ptr = 0; gem_write(fd, create.handle, 0, data, obj_size); /* kernel should clean this up for us */ } -int main(int argc, char **argv) +igt_simple_main { int fd; + igt_skip_on_simulation(); + fd = drm_open_any(); test_large_object(fd); - - return 0; } diff --git a/tests/gem_linear_blits.c b/tests/gem_linear_blits.c index fe15f1d1..3a2fd8dd 100644 --- a/tests/gem_linear_blits.c +++ b/tests/gem_linear_blits.c @@ -36,18 +36,19 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> -#include "drm.h" -#include "i915_drm.h" + +#include <drm.h> + +#include "ioctl_wrappers.h" +#include "intel_chipset.h" #include "drmtest.h" -#include "intel_bufmgr.h" -#include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "igt_aux.h" #define WIDTH 512 #define HEIGHT 512 @@ -57,27 +58,36 @@ static uint32_t linear[WIDTH*HEIGHT]; static void copy(int fd, uint32_t dst, uint32_t src) { - uint32_t batch[10]; + uint32_t batch[12]; struct drm_i915_gem_relocation_entry reloc[2]; struct drm_i915_gem_exec_object2 obj[3]; struct drm_i915_gem_execbuffer2 exec; uint32_t handle; - int ret; + int ret, i=0; - batch[0] = XY_SRC_COPY_BLT_CMD | + batch[i++] = XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB; - batch[1] = (3 << 24) | /* 32 bits */ + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + batch[i - 1] |= 8; + else + batch[i - 1] |= 6; + + batch[i++] = (3 << 24) | /* 32 bits */ (0xcc << 16) | /* copy ROP */ WIDTH*4; - batch[2] = 0; /* dst x1,y1 */ - batch[3] = (HEIGHT << 16) | WIDTH; /* dst x2,y2 */ - batch[4] = 0; /* dst reloc */ - batch[5] = 0; /* src x1,y1 */ - batch[6] = WIDTH*4; - batch[7] = 0; /* src reloc */ - batch[8] = MI_BATCH_BUFFER_END; - batch[9] = MI_NOOP; + batch[i++] = 0; /* dst x1,y1 */ + batch[i++] = (HEIGHT << 16) | WIDTH; /* dst x2,y2 */ + batch[i++] = 0; /* dst reloc */ + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + batch[i++] = 0; + batch[i++] = 0; /* src x1,y1 */ + batch[i++] = WIDTH*4; + batch[i++] = 0; /* src reloc */ + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + batch[i++] = 0; + batch[i++] = MI_BATCH_BUFFER_END; + batch[i++] = MI_NOOP; handle = gem_create(fd, 4096); gem_write(fd, handle, 0, batch, sizeof(batch)); @@ -92,6 +102,8 @@ copy(int fd, uint32_t dst, uint32_t src) reloc[1].target_handle = src; reloc[1].delta = 0; reloc[1].offset = 7 * sizeof(batch[0]); + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + reloc[1].offset += sizeof(batch[0]); reloc[1].presumed_offset = 0; reloc[1].read_domains = I915_GEM_DOMAIN_RENDER;; reloc[1].write_domain = 0; @@ -125,7 +137,7 @@ copy(int fd, uint32_t dst, uint32_t src) exec.buffers_ptr = (uintptr_t)obj; exec.buffer_count = 3; exec.batch_start_offset = 0; - exec.batch_len = sizeof(batch); + exec.batch_len = i * 4; exec.DR1 = exec.DR4 = 0; exec.num_cliprects = 0; exec.cliprects_ptr = 0; @@ -138,7 +150,7 @@ copy(int fd, uint32_t dst, uint32_t src) drmCommandNone(fd, DRM_I915_GEM_THROTTLE); ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); } - assert(ret == 0); + igt_assert(ret == 0); gem_close(fd, handle); } @@ -166,36 +178,19 @@ check_bo(int fd, uint32_t handle, uint32_t val) gem_read(fd, handle, 0, linear, sizeof(linear)); for (i = 0; i < WIDTH*HEIGHT; i++) { - if (linear[i] != val) { - fprintf(stderr, "Expected 0x%08x, found 0x%08x " - "at offset 0x%08x\n", - val, linear[i], i * 4); - abort(); - } + igt_assert_f(linear[i] == val, + "Expected 0x%08x, found 0x%08x " + "at offset 0x%08x\n", + val, linear[i], i * 4); val++; } } -int main(int argc, char **argv) +static void run_test(int fd, int count) { uint32_t *handle, *start_val; uint32_t start = 0; - int i, fd, count; - - fd = drm_open_any(); - - count = 0; - if (argc > 1) - count = atoi(argv[1]); - if (count == 0) - count = 3 * gem_aperture_size(fd) / (1024*1024) / 2; - - if (count > intel_get_total_ram_mb() * 9 / 10) { - count = intel_get_total_ram_mb() * 9 / 10; - printf("not enough RAM to run test, reducing buffer count\n"); - } - - printf("Using %d 1MiB buffers\n", count); + int i; handle = malloc(sizeof(uint32_t)*count*2); start_val = handle + count; @@ -206,11 +201,11 @@ int main(int argc, char **argv) start += 1024 * 1024 / 4; } - printf("Verifying initialisation...\n"); + igt_info("Verifying initialisation...\n"); for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("Cyclic blits, forward...\n"); + igt_info("Cyclic blits, forward...\n"); for (i = 0; i < count * 4; i++) { int src = i % count; int dst = (i + 1) % count; @@ -221,7 +216,7 @@ int main(int argc, char **argv) for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("Cyclic blits, backward...\n"); + igt_info("Cyclic blits, backward...\n"); for (i = 0; i < count * 4; i++) { int src = (i + 1) % count; int dst = i % count; @@ -232,7 +227,7 @@ int main(int argc, char **argv) for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("Random blits...\n"); + igt_info("Random blits...\n"); for (i = 0; i < count * 4; i++) { int src = random() % count; int dst = random() % count; @@ -243,8 +238,50 @@ int main(int argc, char **argv) copy(fd, handle[dst], handle[src]); start_val[dst] = start_val[src]; } - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) { check_bo(fd, handle[i], start_val[i]); + gem_close(fd, handle[i]); + } + + free(handle); +} + +int main(int argc, char **argv) +{ + int fd = 0, count = 0; + + igt_skip_on_simulation(); + + igt_subtest_init(argc, argv); + + igt_fixture { + fd = drm_open_any(); + + if (argc > 1) + count = atoi(argv[1]); + if (count == 0) + count = 3 * gem_aperture_size(fd) / (1024*1024) / 2; + else if (count < 2) { + fprintf(stderr, "count must be >= 2\n"); + return 1; + } + + if (count > intel_get_total_ram_mb() * 9 / 10) { + count = intel_get_total_ram_mb() * 9 / 10; + igt_info("not enough RAM to run test, reducing buffer count\n"); + } + + igt_info("Using %d 1MiB buffers\n", count); + } + + igt_subtest("normal") + run_test(fd, count); + + igt_subtest("interruptible") { + igt_fork_signal_helper(); + run_test(fd, count); + igt_stop_signal_helper(); + } - return 0; + igt_exit(); } diff --git a/tests/gem_lut_handle.c b/tests/gem_lut_handle.c new file mode 100644 index 00000000..d3f6f732 --- /dev/null +++ b/tests/gem_lut_handle.c @@ -0,0 +1,238 @@ +/* + * Copyright © 2012,2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Chris Wilson <chris@chris-wilson.co.uk> + * + */ + +/* Exercises the basic execbuffer using theh andle LUT interface */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> +#include "drm.h" +#include "ioctl_wrappers.h" +#include "drmtest.h" + +#define BATCH_SIZE (1024*1024) + +#define LOCAL_I915_EXEC_HANDLE_LUT (1<<12) + +#define NORMAL 0 +#define USE_LUT 0x1 +#define BROKEN 0x2 + +static int exec(int fd, uint32_t handle, unsigned int flags) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 gem_exec[1]; + struct drm_i915_gem_relocation_entry gem_reloc[1]; + + gem_reloc[0].offset = 1024; + gem_reloc[0].delta = 0; + gem_reloc[0].target_handle = + !!(flags & USE_LUT) ^ !!(flags & BROKEN) ? 0 : handle; + gem_reloc[0].read_domains = I915_GEM_DOMAIN_RENDER; + gem_reloc[0].write_domain = 0; + gem_reloc[0].presumed_offset = 0; + + gem_exec[0].handle = handle; + gem_exec[0].relocation_count = 1; + gem_exec[0].relocs_ptr = (uintptr_t) gem_reloc; + gem_exec[0].alignment = 0; + gem_exec[0].offset = 0; + gem_exec[0].flags = 0; + gem_exec[0].rsvd1 = 0; + gem_exec[0].rsvd2 = 0; + + execbuf.buffers_ptr = (uintptr_t)gem_exec; + execbuf.buffer_count = 1; + execbuf.batch_start_offset = 0; + execbuf.batch_len = 8; + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = flags & USE_LUT ? LOCAL_I915_EXEC_HANDLE_LUT : 0; + i915_execbuffer2_set_context_id(execbuf, 0); + execbuf.rsvd2 = 0; + + if (drmIoctl(fd, + DRM_IOCTL_I915_GEM_EXECBUFFER2, + &execbuf)) + return -errno; + + return 0; +} + +static int many_exec(int fd, uint32_t batch, int num_exec, int num_reloc, unsigned flags) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 *gem_exec; + struct drm_i915_gem_relocation_entry *gem_reloc; + unsigned max_handle = batch; + int ret, n; + + gem_exec = calloc(num_exec+1, sizeof(*gem_exec)); + gem_reloc = calloc(num_reloc, sizeof(*gem_reloc)); + igt_assert(gem_exec && gem_reloc); + + for (n = 0; n < num_exec; n++) { + gem_exec[n].handle = gem_create(fd, 4096); + if (gem_exec[n].handle > max_handle) + max_handle = gem_exec[n].handle; + gem_exec[n].relocation_count = 0; + gem_exec[n].relocs_ptr = 0; + gem_exec[n].alignment = 0; + gem_exec[n].offset = 0; + gem_exec[n].flags = 0; + gem_exec[n].rsvd1 = 0; + gem_exec[n].rsvd2 = 0; + } + + gem_exec[n].handle = batch; + gem_exec[n].relocation_count = num_reloc; + gem_exec[n].relocs_ptr = (uintptr_t) gem_reloc; + + if (flags & USE_LUT) + max_handle = num_exec + 1; + max_handle++; + + for (n = 0; n < num_reloc; n++) { + uint32_t target; + + if (flags & BROKEN) { + target = -(rand() % 4096) - 1; + } else { + target = rand() % (num_exec + 1); + if ((flags & USE_LUT) == 0) + target = gem_exec[target].handle; + } + + gem_reloc[n].offset = 1024; + gem_reloc[n].delta = 0; + gem_reloc[n].target_handle = target; + gem_reloc[n].read_domains = I915_GEM_DOMAIN_RENDER; + gem_reloc[n].write_domain = 0; + gem_reloc[n].presumed_offset = 0; + } + + execbuf.buffers_ptr = (uintptr_t)gem_exec; + execbuf.buffer_count = num_exec + 1; + execbuf.batch_start_offset = 0; + execbuf.batch_len = 8; + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = flags & USE_LUT ? LOCAL_I915_EXEC_HANDLE_LUT : 0; + i915_execbuffer2_set_context_id(execbuf, 0); + execbuf.rsvd2 = 0; + + ret = drmIoctl(fd, + DRM_IOCTL_I915_GEM_EXECBUFFER2, + &execbuf); + if (ret < 0) + ret = -errno; + + for (n = 0; n < num_exec; n++) + gem_close(fd, gem_exec[n].handle); + + free(gem_exec); + free(gem_reloc); + + return ret; +} + +#define fail(x) igt_assert((x) == -ENOENT) +#define pass(x) igt_assert((x) == 0) + +igt_simple_main +{ + uint32_t batch[2] = {MI_BATCH_BUFFER_END}; + uint32_t handle; + int fd, i; + + fd = drm_open_any(); + + handle = gem_create(fd, 4096); + gem_write(fd, handle, 0, batch, sizeof(batch)); + + do_or_die(exec(fd, handle, NORMAL)); + fail(exec(fd, handle, BROKEN)); + + igt_skip_on(exec(fd, handle, USE_LUT)); + + do_or_die(exec(fd, handle, USE_LUT)); + fail(exec(fd, handle, USE_LUT | BROKEN)); + + for (i = 2; i <= SLOW_QUICK(65536, 8); i *= 2) { + if (many_exec(fd, handle, i+1, i+1, NORMAL) == -ENOSPC) + break; + + pass(many_exec(fd, handle, i-1, i-1, NORMAL)); + pass(many_exec(fd, handle, i-1, i, NORMAL)); + pass(many_exec(fd, handle, i-1, i+1, NORMAL)); + pass(many_exec(fd, handle, i, i-1, NORMAL)); + pass(many_exec(fd, handle, i, i, NORMAL)); + pass(many_exec(fd, handle, i, i+1, NORMAL)); + pass(many_exec(fd, handle, i+1, i-1, NORMAL)); + pass(many_exec(fd, handle, i+1, i, NORMAL)); + pass(many_exec(fd, handle, i+1, i+1, NORMAL)); + + fail(many_exec(fd, handle, i-1, i-1, NORMAL | BROKEN)); + fail(many_exec(fd, handle, i-1, i, NORMAL | BROKEN)); + fail(many_exec(fd, handle, i-1, i+1, NORMAL | BROKEN)); + fail(many_exec(fd, handle, i, i-1, NORMAL | BROKEN)); + fail(many_exec(fd, handle, i, i, NORMAL | BROKEN)); + fail(many_exec(fd, handle, i, i+1, NORMAL | BROKEN)); + fail(many_exec(fd, handle, i+1, i-1, NORMAL | BROKEN)); + fail(many_exec(fd, handle, i+1, i, NORMAL | BROKEN)); + fail(many_exec(fd, handle, i+1, i+1, NORMAL | BROKEN)); + + pass(many_exec(fd, handle, i-1, i-1, USE_LUT)); + pass(many_exec(fd, handle, i-1, i, USE_LUT)); + pass(many_exec(fd, handle, i-1, i+1, USE_LUT)); + pass(many_exec(fd, handle, i, i-1, USE_LUT)); + pass(many_exec(fd, handle, i, i, USE_LUT)); + pass(many_exec(fd, handle, i, i+1, USE_LUT)); + pass(many_exec(fd, handle, i+1, i-1, USE_LUT)); + pass(many_exec(fd, handle, i+1, i, USE_LUT)); + pass(many_exec(fd, handle, i+1, i+1, USE_LUT)); + + fail(many_exec(fd, handle, i-1, i-1, USE_LUT | BROKEN)); + fail(many_exec(fd, handle, i-1, i, USE_LUT | BROKEN)); + fail(many_exec(fd, handle, i-1, i+1, USE_LUT | BROKEN)); + fail(many_exec(fd, handle, i, i-1, USE_LUT | BROKEN)); + fail(many_exec(fd, handle, i, i, USE_LUT | BROKEN)); + fail(many_exec(fd, handle, i, i+1, USE_LUT | BROKEN)); + fail(many_exec(fd, handle, i+1, i-1, USE_LUT | BROKEN)); + fail(many_exec(fd, handle, i+1, i, USE_LUT | BROKEN)); + fail(many_exec(fd, handle, i+1, i+1, USE_LUT | BROKEN)); + } +} diff --git a/tests/gem_madvise.c b/tests/gem_madvise.c new file mode 100644 index 00000000..04a82aa3 --- /dev/null +++ b/tests/gem_madvise.c @@ -0,0 +1,155 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Chris Wilson <chris@chris-wilson.co.uk> + * + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <setjmp.h> +#include <signal.h> + +#include "drm.h" +#include "ioctl_wrappers.h" +#include "drmtest.h" + +#define OBJECT_SIZE (1024*1024) + +/* Testcase: checks that the kernel reports EFAULT when trying to use purged bo + * + */ + +static jmp_buf jmp; + +static void sigtrap(int sig) +{ + longjmp(jmp, sig); +} + +static void +dontneed_before_mmap(void) +{ + int fd = drm_open_any(); + uint32_t handle; + char *ptr; + + handle = gem_create(fd, OBJECT_SIZE); + gem_madvise(fd, handle, I915_MADV_DONTNEED); + ptr = gem_mmap(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE); + igt_assert(ptr == NULL); + igt_assert(errno == EFAULT); + close(fd); +} + +static void +dontneed_after_mmap(void) +{ + int fd = drm_open_any(); + uint32_t handle; + char *ptr; + + handle = gem_create(fd, OBJECT_SIZE); + ptr = gem_mmap(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE); + igt_assert(ptr != NULL); + gem_madvise(fd, handle, I915_MADV_DONTNEED); + close(fd); + + signal(SIGBUS, sigtrap); + switch (setjmp(jmp)) { + case SIGBUS: + break; + case 0: + *ptr = 0; + default: + igt_assert(!"reached"); + break; + } + munmap(ptr, OBJECT_SIZE); + signal(SIGBUS, SIG_DFL); +} + +static void +dontneed_before_pwrite(void) +{ + int fd = drm_open_any(); + uint32_t buf[] = { MI_BATCH_BUFFER_END, 0 }; + struct drm_i915_gem_pwrite gem_pwrite; + + gem_pwrite.handle = gem_create(fd, OBJECT_SIZE); + gem_pwrite.offset = 0; + gem_pwrite.size = sizeof(buf); + gem_pwrite.data_ptr = (uintptr_t)buf; + gem_madvise(fd, gem_pwrite.handle, I915_MADV_DONTNEED); + + igt_assert(drmIoctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &gem_pwrite)); + igt_assert(errno == EFAULT); + + gem_close(fd, gem_pwrite.handle); + close(fd); +} + +static void +dontneed_before_exec(void) +{ + int fd = drm_open_any(); + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 exec; + uint32_t buf[] = { MI_BATCH_BUFFER_END, 0 }; + + memset(&execbuf, 0, sizeof(execbuf)); + memset(&exec, 0, sizeof(exec)); + + exec.handle = gem_create(fd, OBJECT_SIZE); + gem_write(fd, exec.handle, 0, buf, sizeof(buf)); + gem_madvise(fd, exec.handle, I915_MADV_DONTNEED); + + execbuf.buffers_ptr = (uintptr_t)&exec; + execbuf.buffer_count = 1; + gem_execbuf(fd, &execbuf); + + gem_close(fd, exec.handle); + close(fd); +} + +igt_main +{ + igt_skip_on_simulation(); + + igt_subtest("dontneed-before-mmap") + dontneed_before_mmap(); + + igt_subtest("dontneed-after-mmap") + dontneed_after_mmap(); + + igt_subtest("dontneed-before-pwrite") + dontneed_before_pwrite(); + + igt_subtest("dontneed-before-exec") + dontneed_before_exec(); +} diff --git a/tests/gem_media_fill.c b/tests/gem_media_fill.c new file mode 100644 index 00000000..db2380b4 --- /dev/null +++ b/tests/gem_media_fill.c @@ -0,0 +1,142 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Damien Lespiau <damien.lespiau@intel.com> + * Xiang, Haihao <haihao.xiang@intel.com> + */ + +/* + * This file is a basic test for the media_fill() function, a very simple + * workload for the Media pipeline. + */ + +#include <stdbool.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <getopt.h> +#include "drm.h" +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_io.h" +#include "intel_chipset.h" + +#define WIDTH 64 +#define STRIDE (WIDTH) +#define HEIGHT 64 +#define SIZE (HEIGHT*STRIDE) + +#define COLOR_C4 0xc4 +#define COLOR_4C 0x4c + +typedef struct { + int drm_fd; + uint32_t devid; + drm_intel_bufmgr *bufmgr; + uint8_t linear[WIDTH * HEIGHT]; +} data_t; + +static void scratch_buf_init(data_t *data, struct igt_buf *buf, + int width, int height, int stride, uint8_t color) +{ + drm_intel_bo *bo; + int i; + + bo = drm_intel_bo_alloc(data->bufmgr, "", SIZE, 4096); + for (i = 0; i < width * height; i++) + data->linear[i] = color; + gem_write(data->drm_fd, bo->handle, 0, data->linear, + sizeof(data->linear)); + + buf->bo = bo; + buf->stride = stride; + buf->tiling = I915_TILING_NONE; + buf->size = SIZE; +} + +static void +scratch_buf_check(data_t *data, struct igt_buf *buf, int x, int y, + uint8_t color) +{ + uint8_t val; + + gem_read(data->drm_fd, buf->bo->handle, 0, + data->linear, sizeof(data->linear)); + val = data->linear[y * WIDTH + x]; + igt_assert_f(val == color, + "Expected 0x%02x, found 0x%02x at (%d,%d)\n", + color, val, x, y); +} + +igt_simple_main +{ + data_t data = {0, }; + struct intel_batchbuffer *batch = NULL; + struct igt_buf dst; + igt_media_fillfunc_t media_fill = NULL; + int i, j; + + data.drm_fd = drm_open_any_render(); + data.devid = intel_get_drm_devid(data.drm_fd); + + data.bufmgr = drm_intel_bufmgr_gem_init(data.drm_fd, 4096); + igt_assert(data.bufmgr); + + media_fill = igt_get_media_fillfunc(data.devid); + + igt_require_f(media_fill, + "no media-fill function\n"); + + batch = intel_batchbuffer_alloc(data.bufmgr, data.devid); + igt_assert(batch); + + scratch_buf_init(&data, &dst, WIDTH, HEIGHT, STRIDE, COLOR_C4); + + for (i = 0; i < WIDTH; i++) { + for (j = 0; j < HEIGHT; j++) { + scratch_buf_check(&data, &dst, i, j, COLOR_C4); + } + } + + media_fill(batch, + &dst, 0, 0, WIDTH / 2, HEIGHT / 2, + COLOR_4C); + + for (i = 0; i < WIDTH; i++) { + for (j = 0; j < HEIGHT; j++) { + if (i < WIDTH / 2 && j < HEIGHT / 2) + scratch_buf_check(&data, &dst, i, j, COLOR_4C); + else + scratch_buf_check(&data, &dst, i, j, COLOR_C4); + } + } +} diff --git a/tests/gem_mmap.c b/tests/gem_mmap.c index f9369f43..46ef3ece 100644 --- a/tests/gem_mmap.c +++ b/tests/gem_mmap.c @@ -29,68 +29,69 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/ioctl.h> -#include <sys/mman.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #define OBJECT_SIZE 16384 +int fd; +int handle; -int main(int argc, char **argv) +igt_main { - int fd; struct drm_i915_gem_mmap arg; uint8_t expected[OBJECT_SIZE]; uint8_t buf[OBJECT_SIZE]; uint8_t *addr; int ret; - int handle; - fd = drm_open_any(); + igt_fixture + fd = drm_open_any(); - memset(&arg, 0, sizeof(arg)); - arg.handle = 0x10101010; - arg.offset = 0; - arg.size = 4096; - printf("Testing mmaping of bad object.\n"); - ret = ioctl(fd, DRM_IOCTL_I915_GEM_MMAP, &arg); - assert(ret == -1 && errno == ENOENT); + igt_subtest("bad-object") { + memset(&arg, 0, sizeof(arg)); + arg.handle = 0x10101010; + arg.offset = 0; + arg.size = 4096; + ret = ioctl(fd, DRM_IOCTL_I915_GEM_MMAP, &arg); + igt_assert(ret == -1 && errno == ENOENT); + } - handle = gem_create(fd, OBJECT_SIZE); + igt_fixture + handle = gem_create(fd, OBJECT_SIZE); - printf("Testing mmaping of newly created object.\n"); - arg.handle = handle; - arg.offset = 0; - arg.size = OBJECT_SIZE; - ret = ioctl(fd, DRM_IOCTL_I915_GEM_MMAP, &arg); - assert(ret == 0); - addr = (uint8_t *)(uintptr_t)arg.addr_ptr; + igt_subtest("new-object") { + arg.handle = handle; + arg.offset = 0; + arg.size = OBJECT_SIZE; + ret = ioctl(fd, DRM_IOCTL_I915_GEM_MMAP, &arg); + igt_assert(ret == 0); + addr = (uint8_t *)(uintptr_t)arg.addr_ptr; - printf("Testing contents of newly created object.\n"); - memset(expected, 0, sizeof(expected)); - assert(memcmp(addr, expected, sizeof(expected)) == 0); + igt_info("Testing contents of newly created object.\n"); + memset(expected, 0, sizeof(expected)); + igt_assert(memcmp(addr, expected, sizeof(expected)) == 0); - printf("Testing coherency of writes and mmap reads.\n"); - memset(buf, 0, sizeof(buf)); - memset(buf + 1024, 0x01, 1024); - memset(expected + 1024, 0x01, 1024); - gem_write(fd, handle, 0, buf, OBJECT_SIZE); - assert(memcmp(buf, addr, sizeof(buf)) == 0); + igt_info("Testing coherency of writes and mmap reads.\n"); + memset(buf, 0, sizeof(buf)); + memset(buf + 1024, 0x01, 1024); + memset(expected + 1024, 0x01, 1024); + gem_write(fd, handle, 0, buf, OBJECT_SIZE); + igt_assert(memcmp(buf, addr, sizeof(buf)) == 0); - printf("Testing that mapping stays after close\n"); - gem_close(fd, handle); - assert(memcmp(buf, addr, sizeof(buf)) == 0); + igt_info("Testing that mapping stays after close\n"); + gem_close(fd, handle); + igt_assert(memcmp(buf, addr, sizeof(buf)) == 0); - printf("Testing unmapping\n"); - munmap(addr, OBJECT_SIZE); + igt_info("Testing unmapping\n"); + munmap(addr, OBJECT_SIZE); + } - close(fd); - - return 0; + igt_fixture + close(fd); } diff --git a/tests/gem_mmap_gtt.c b/tests/gem_mmap_gtt.c index e7a48679..7ba5e39c 100644 --- a/tests/gem_mmap_gtt.c +++ b/tests/gem_mmap_gtt.c @@ -25,22 +25,22 @@ * */ +#define _GNU_SOURCE #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/ioctl.h> -#include <sys/mman.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" +#include "igt_debugfs.h" -#define OBJECT_SIZE (16*1024*1024) +static int OBJECT_SIZE = 16*1024*1024; static void set_domain(int fd, uint32_t handle) { @@ -53,7 +53,7 @@ mmap_bo(int fd, uint32_t handle) void *ptr; ptr = gem_mmap(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE); - assert(ptr != MAP_FAILED); + igt_assert(ptr != MAP_FAILED); return ptr; } @@ -74,6 +74,43 @@ create_pointer(int fd) } static void +test_access(int fd) +{ + uint32_t handle, flink, handle2; + struct drm_i915_gem_mmap_gtt mmap_arg; + int fd2; + + handle = gem_create(fd, OBJECT_SIZE); + igt_assert(handle); + + fd2 = drm_open_any(); + + /* Check that fd1 can mmap. */ + mmap_arg.handle = handle; + igt_assert(drmIoctl(fd, + DRM_IOCTL_I915_GEM_MMAP_GTT, + &mmap_arg) == 0); + + igt_assert(mmap64(0, OBJECT_SIZE, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, mmap_arg.offset)); + + /* Check that the same offset on the other fd doesn't work. */ + igt_assert(mmap64(0, OBJECT_SIZE, PROT_READ | PROT_WRITE, + MAP_SHARED, fd2, mmap_arg.offset) == MAP_FAILED); + igt_assert(errno == EACCES); + + flink = gem_flink(fd, handle); + igt_assert(flink); + handle2 = gem_open(fd2, flink); + igt_assert(handle2); + + /* Recheck that it works after flink. */ + /* Check that the same offset on the other fd doesn't work. */ + igt_assert(mmap64(0, OBJECT_SIZE, PROT_READ | PROT_WRITE, + MAP_SHARED, fd2, mmap_arg.offset)); +} + +static void test_copy(int fd) { void *src, *dst; @@ -144,18 +181,42 @@ test_read(int fd) munmap(dst, OBJECT_SIZE); } -int main(int argc, char **argv) +static void +run_without_prefault(int fd, + void (*func)(int fd)) { - int fd; - - fd = drm_open_any(); - - test_copy(fd); - test_read(fd); - test_write(fd); - test_write_gtt(fd); + igt_disable_prefault(); + func(fd); + igt_enable_prefault(); +} - close(fd); +int fd; - return 0; +igt_main +{ + if (igt_run_in_simulation()) + OBJECT_SIZE = 1 * 1024 * 1024; + + igt_fixture + fd = drm_open_any(); + + igt_subtest("access") + test_access(fd); + igt_subtest("copy") + test_copy(fd); + igt_subtest("read") + test_read(fd); + igt_subtest("write") + test_write(fd); + igt_subtest("write-gtt") + test_write_gtt(fd); + igt_subtest("read-no-prefault") + run_without_prefault(fd, test_read); + igt_subtest("write-no-prefault") + run_without_prefault(fd, test_write); + igt_subtest("write-gtt-no-prefault") + run_without_prefault(fd, test_write_gtt); + + igt_fixture + close(fd); } diff --git a/tests/gem_mmap_offset_exhaustion.c b/tests/gem_mmap_offset_exhaustion.c index 51ae5990..914fe6eb 100644 --- a/tests/gem_mmap_offset_exhaustion.c +++ b/tests/gem_mmap_offset_exhaustion.c @@ -29,15 +29,13 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/ioctl.h> -#include <sys/mman.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #define OBJECT_SIZE (1024*1024) @@ -61,11 +59,7 @@ create_and_map_bo(int fd) handle = gem_create(fd, OBJECT_SIZE); ptr = gem_mmap(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE); - - if (!ptr) { - fprintf(stderr, "mmap failed\n"); - assert(ptr); - } + igt_assert(ptr); /* touch it to force it into the gtt */ *ptr = 0; @@ -79,10 +73,12 @@ create_and_map_bo(int fd) gem_madvise(fd, handle, I915_MADV_DONTNEED); } -int main(int argc, char **argv) +igt_simple_main { int fd, i; + igt_skip_on_simulation(); + fd = drm_open_any(); /* we have 32bit of address space, so try to fit one MB more @@ -91,6 +87,4 @@ int main(int argc, char **argv) create_and_map_bo(fd); close(fd); - - return 0; } diff --git a/tests/gem_multi_bsd_sync_loop.c b/tests/gem_multi_bsd_sync_loop.c new file mode 100644 index 00000000..003da42f --- /dev/null +++ b/tests/gem_multi_bsd_sync_loop.c @@ -0,0 +1,164 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Daniel Vetter <daniel.vetter@ffwll.ch> (based on gem_ring_sync_loop_*.c) + * Zhao Yakui <yakui.zhao@intel.com> + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> +#include "drm.h" +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_io.h" +#include "i830_reg.h" +#include "intel_chipset.h" + +static drm_intel_bufmgr *bufmgr; +struct intel_batchbuffer *batch; +static drm_intel_bo *target_buffer; + +#define NUM_FD 50 + +static int mfd[NUM_FD]; +static drm_intel_bufmgr *mbufmgr[NUM_FD]; +static struct intel_batchbuffer *mbatch[NUM_FD]; +static drm_intel_bo *mbuffer[NUM_FD]; + + +/* + * Testcase: Basic check of ring<->ring sync using a dummy reloc + * + * Extremely efficient at catching missed irqs with semaphores=0 ... + */ + +#define MI_COND_BATCH_BUFFER_END (0x36<<23 | 1) +#define MI_DO_COMPARE (1<<21) + +static void +store_dword_loop(int fd) +{ + int i; + int num_rings = gem_get_num_rings(fd); + + srandom(0xdeadbeef); + + for (i = 0; i < SLOW_QUICK(0x100000, 10); i++) { + int ring, mindex; + ring = random() % num_rings + 1; + mindex = random() % NUM_FD; + batch = mbatch[mindex]; + if (ring == I915_EXEC_RENDER) { + BEGIN_BATCH(4); + OUT_BATCH(MI_COND_BATCH_BUFFER_END | MI_DO_COMPARE); + OUT_BATCH(0xffffffff); /* compare dword */ + OUT_RELOC(mbuffer[mindex], I915_GEM_DOMAIN_RENDER, + I915_GEM_DOMAIN_RENDER, 0); + OUT_BATCH(MI_NOOP); + ADVANCE_BATCH(); + } else { + BEGIN_BATCH(4); + OUT_BATCH(MI_FLUSH_DW | 1); + OUT_BATCH(0); /* reserved */ + OUT_RELOC(mbuffer[mindex], I915_GEM_DOMAIN_RENDER, + I915_GEM_DOMAIN_RENDER, 0); + OUT_BATCH(MI_NOOP | (1<<22) | (0xf)); + ADVANCE_BATCH(); + } + intel_batchbuffer_flush_on_ring(batch, ring); + } + + drm_intel_bo_map(target_buffer, 0); + // map to force waiting on rendering + drm_intel_bo_unmap(target_buffer); +} + +igt_simple_main +{ + int fd; + int devid; + int i; + + fd = drm_open_any(); + devid = intel_get_drm_devid(fd); + gem_require_ring(fd, I915_EXEC_BLT); + + + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + igt_assert_f(bufmgr, "fail to initialize the buf manager\n"); + drm_intel_bufmgr_gem_enable_reuse(bufmgr); + + + target_buffer = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096); + igt_assert_f(target_buffer, "fail to create the gem bo\n"); + + /* Create multiple drm_fd and map one gem_object among multi drm_fd */ + { + unsigned int target_flink; + char buffer_name[32]; + igt_assert(dri_bo_flink(target_buffer, &target_flink) == 0); + + for (i = 0; i < NUM_FD; i++) { + sprintf(buffer_name, "Target buffer %d\n", i); + mfd[i] = drm_open_any(); + mbufmgr[i] = drm_intel_bufmgr_gem_init(mfd[i], 4096); + igt_assert_f(mbufmgr[i], + "fail to initialize buf manager for drm_fd %d\n", + mfd[i]); + drm_intel_bufmgr_gem_enable_reuse(mbufmgr[i]); + mbatch[i] = intel_batchbuffer_alloc(mbufmgr[i], devid); + igt_assert_f(mbatch[i], + "fail to create batchbuffer for drm_fd %d\n", + mfd[i]); + mbuffer[i] = intel_bo_gem_create_from_name(mbufmgr[i], buffer_name, target_flink); + igt_assert_f(mbuffer[i], + "fail to create buffer bo from global " + "gem handle %d for drm_fd %d\n", + target_flink, mfd[i]); + } + } + + store_dword_loop(fd); + + { + for (i = 0; i < NUM_FD; i++) { + dri_bo_unreference(mbuffer[i]); + intel_batchbuffer_free(mbatch[i]); + drm_intel_bufmgr_destroy(mbufmgr[i]); + close(mfd[i]); + } + } + drm_intel_bo_unreference(target_buffer); + drm_intel_bufmgr_destroy(bufmgr); + + close(fd); +} diff --git a/tests/gem_non_secure_batch.c b/tests/gem_non_secure_batch.c new file mode 100644 index 00000000..9acfda47 --- /dev/null +++ b/tests/gem_non_secure_batch.c @@ -0,0 +1,113 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Daniel Vetter <daniel.vetter@ffwll.ch> (based on gem_storedw_*.c) + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> +#include "drm.h" +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_chipset.h" +#include "intel_io.h" +#include "i830_reg.h" + +static drm_intel_bufmgr *bufmgr; +struct intel_batchbuffer *batch; + +/* + * Testcase: Basic check of non-secure batches + * + * This test tries to stop the render ring with a MI_LOAD_REG command, which + * should fail if the non-secure handling works correctly. + */ + +#define MI_LOAD_REGISTER_IMM (0x22<<23) + +static int num_rings = 1; + +static void +mi_lri_loop(void) +{ + int i; + + srandom(0xdeadbeef); + + for (i = 0; i < 0x100; i++) { + int ring = random() % num_rings + 1; + + BEGIN_BATCH(4); + OUT_BATCH(MI_LOAD_REGISTER_IMM | 1); + OUT_BATCH(0x203c); /* RENDER RING CTL */ + OUT_BATCH(0); /* try to stop the ring */ + OUT_BATCH(MI_NOOP); + ADVANCE_BATCH(); + + intel_batchbuffer_flush_on_ring(batch, ring); + } +} + +int main(int argc, char **argv) +{ + int fd; + int devid; + + fd = drm_open_any(); + devid = intel_get_drm_devid(fd); + + if (HAS_BSD_RING(devid)) + num_rings++; + + if (HAS_BLT_RING(devid)) + num_rings++; + + + igt_info("num rings detected: %i\n", num_rings); + + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + igt_assert(bufmgr); + drm_intel_bufmgr_gem_enable_reuse(bufmgr); + + batch = intel_batchbuffer_alloc(bufmgr, devid); + igt_assert(batch); + + mi_lri_loop(); + gem_quiescent_gpu(fd); + + intel_batchbuffer_free(batch); + drm_intel_bufmgr_destroy(bufmgr); + + close(fd); + + return 0; +} diff --git a/tests/gem_partial_pwrite_pread.c b/tests/gem_partial_pwrite_pread.c index 5c8f6f5f..7945ba79 100644 --- a/tests/gem_partial_pwrite_pread.c +++ b/tests/gem_partial_pwrite_pread.c @@ -28,18 +28,19 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> -#include "drm.h" -#include "i915_drm.h" + +#include <drm.h> + +#include "ioctl_wrappers.h" #include "drmtest.h" -#include "intel_bufmgr.h" -#include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_chipset.h" +#include "intel_io.h" +#include "igt_aux.h" /* * Testcase: pwrite/pread consistency when touching partial cachelines @@ -62,19 +63,18 @@ int fd; static void copy_bo(drm_intel_bo *src, drm_intel_bo *dst) { - BEGIN_BATCH(8); - OUT_BATCH(XY_SRC_COPY_BLT_CMD | - XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); + BLIT_COPY_BATCH_START(devid, 0); OUT_BATCH((3 << 24) | /* 32 bits */ (0xcc << 16) | /* copy ROP */ 4096); OUT_BATCH(0 << 16 | 0); OUT_BATCH((BO_SIZE/4096) << 16 | 1024); OUT_RELOC_FENCED(dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(devid); OUT_BATCH(0 << 16 | 0); OUT_BATCH(4096); OUT_RELOC_FENCED(src, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(devid); ADVANCE_BATCH(); intel_batchbuffer_flush(batch); @@ -96,36 +96,20 @@ blt_bo_fill(drm_intel_bo *tmp_bo, drm_intel_bo *bo, int val) if (bo->offset < mappable_gtt_limit && (IS_G33(devid) || intel_gen(devid) >= 4)) - drmtest_trash_aperture(); + igt_trash_aperture(); copy_bo(tmp_bo, bo); } #define MAX_BLT_SIZE 128 #define ROUNDS 1000 -int main(int argc, char **argv) +uint8_t tmp[BO_SIZE]; + +static void test_partial_reads(void) { int i, j; - uint8_t tmp[BO_SIZE]; - uint8_t *gtt_ptr; - - srandom(0xdeadbeef); - fd = drm_open_any(); - - bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - //drm_intel_bufmgr_gem_enable_reuse(bufmgr); - devid = intel_get_drm_devid(fd); - batch = intel_batchbuffer_alloc(bufmgr, devid); - - /* overallocate the buffers we're actually using because */ - scratch_bo = drm_intel_bo_alloc(bufmgr, "scratch bo", BO_SIZE, 4096); - staging_bo = drm_intel_bo_alloc(bufmgr, "staging bo", BO_SIZE, 4096); - - drmtest_init_aperture_trashers(bufmgr); - mappable_gtt_limit = gem_mappable_aperture_size(); - - printf("checking partial reads\n"); + igt_info("checking partial reads\n"); for (i = 0; i < ROUNDS; i++) { int start, len; int val = i % 256; @@ -137,17 +121,22 @@ int main(int argc, char **argv) drm_intel_bo_get_subdata(scratch_bo, start, len, tmp); for (j = 0; j < len; j++) { - if (tmp[j] != val) { - printf("mismatch at %i, got: %i, expected: %i\n", - j, tmp[j], val); - exit(1); - } + igt_assert_f(tmp[j] == val, + "mismatch at %i, got: %i, expected: %i\n", + j, tmp[j], val); } - drmtest_progress("partial reads test: ", i, ROUNDS); + igt_progress("partial reads test: ", i, ROUNDS); } - printf("checking partial writes\n"); +} + +static void test_partial_writes(void) +{ + int i, j; + uint8_t *gtt_ptr; + + igt_info("checking partial writes\n"); for (i = 0; i < ROUNDS; i++) { int start, len; int val = i % 256; @@ -166,32 +155,33 @@ int main(int argc, char **argv) gtt_ptr = staging_bo->virtual; for (j = 0; j < start; j++) { - if (gtt_ptr[j] != val) { - printf("mismatch at %i, got: %i, expected: %i\n", - j, tmp[j], val); - exit(1); - } + igt_assert_f(gtt_ptr[j] == val, + "mismatch at %i, got: %i, expected: %i\n", + j, tmp[j], val); } for (; j < start + len; j++) { - if (gtt_ptr[j] != tmp[0]) { - printf("mismatch at %i, got: %i, expected: %i\n", - j, tmp[j], i); - exit(1); - } + igt_assert_f(gtt_ptr[j] == tmp[0], + "mismatch at %i, got: %i, expected: %i\n", + j, tmp[j], i); } for (; j < BO_SIZE; j++) { - if (gtt_ptr[j] != val) { - printf("mismatch at %i, got: %i, expected: %i\n", - j, tmp[j], val); - exit(1); - } + igt_assert_f(gtt_ptr[j] == val, + "mismatch at %i, got: %i, expected: %i\n", + j, tmp[j], val); } drm_intel_gem_bo_unmap_gtt(staging_bo); - drmtest_progress("partial writes test: ", i, ROUNDS); + igt_progress("partial writes test: ", i, ROUNDS); } - printf("checking partial writes after partial reads\n"); +} + +static void test_partial_read_writes(void) +{ + int i, j; + uint8_t *gtt_ptr; + + igt_info("checking partial writes after partial reads\n"); for (i = 0; i < ROUNDS; i++) { int start, len; int val = i % 256; @@ -204,11 +194,9 @@ int main(int argc, char **argv) drm_intel_bo_get_subdata(scratch_bo, start, len, tmp); for (j = 0; j < len; j++) { - if (tmp[j] != val) { - printf("mismatch in read at %i, got: %i, expected: %i\n", - j, tmp[j], val); - exit(1); - } + igt_assert_f(tmp[j] == val, + "mismatch in read at %i, got: %i, expected: %i\n", + j, tmp[j], val); } /* Change contents through gtt to make the pread cachelines @@ -229,35 +217,76 @@ int main(int argc, char **argv) gtt_ptr = staging_bo->virtual; for (j = 0; j < start; j++) { - if (gtt_ptr[j] != val) { - printf("mismatch at %i, got: %i, expected: %i\n", - j, tmp[j], val); - exit(1); - } + igt_assert_f(gtt_ptr[j] == val, + "mismatch at %i, got: %i, expected: %i\n", + j, tmp[j], val); } for (; j < start + len; j++) { - if (gtt_ptr[j] != tmp[0]) { - printf("mismatch at %i, got: %i, expected: %i\n", - j, tmp[j], tmp[0]); - exit(1); - } + igt_assert_f(gtt_ptr[j] == tmp[0], + "mismatch at %i, got: %i, expected: %i\n", + j, tmp[j], tmp[0]); } for (; j < BO_SIZE; j++) { - if (gtt_ptr[j] != val) { - printf("mismatch at %i, got: %i, expected: %i\n", - j, tmp[j], val); - exit(1); - } + igt_assert_f(gtt_ptr[j] == val, + "mismatch at %i, got: %i, expected: %i\n", + j, tmp[j], val); } drm_intel_gem_bo_unmap_gtt(staging_bo); - drmtest_progress("partial read/writes test: ", i, ROUNDS); + igt_progress("partial read/writes test: ", i, ROUNDS); + } +} + +static void do_tests(int cache_level, const char *suffix) +{ + igt_fixture { + if (cache_level != -1) + gem_set_caching(fd, scratch_bo->handle, cache_level); + } + + igt_subtest_f("reads%s", suffix) + test_partial_reads(); + + igt_subtest_f("write%s", suffix) + test_partial_writes(); + + igt_subtest_f("writes-after-reads%s", suffix) + test_partial_read_writes(); +} + +igt_main +{ + srandom(0xdeadbeef); + + igt_skip_on_simulation(); + + igt_fixture { + fd = drm_open_any(); + + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + //drm_intel_bufmgr_gem_enable_reuse(bufmgr); + devid = intel_get_drm_devid(fd); + batch = intel_batchbuffer_alloc(bufmgr, devid); + + /* overallocate the buffers we're actually using because */ + scratch_bo = drm_intel_bo_alloc(bufmgr, "scratch bo", BO_SIZE, 4096); + staging_bo = drm_intel_bo_alloc(bufmgr, "staging bo", BO_SIZE, 4096); + + igt_init_aperture_trashers(bufmgr); + mappable_gtt_limit = gem_mappable_aperture_size(); } - drmtest_cleanup_aperture_trashers(); - drm_intel_bufmgr_destroy(bufmgr); + do_tests(-1, ""); - close(fd); + /* Repeat the tests using different levels of snooping */ + do_tests(0, "-uncached"); + do_tests(1, "-snoop"); + do_tests(2, "-display"); - return 0; + igt_fixture { + igt_cleanup_aperture_trashers(); + drm_intel_bufmgr_destroy(bufmgr); + + close(fd); + } } diff --git a/tests/gem_persistent_relocs.c b/tests/gem_persistent_relocs.c new file mode 100644 index 00000000..8b5a62ef --- /dev/null +++ b/tests/gem_persistent_relocs.c @@ -0,0 +1,365 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Daniel Vetter <daniel.vetter@ffwll.ch> + * + */ + +#define _GNU_SOURCE +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <signal.h> +#include <sys/wait.h> + +#include <drm.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_chipset.h" +#include "intel_io.h" +#include "igt_debugfs.h" +#include "igt_aux.h" + +/* + * Testcase: Persistent relocations as used by uxa/libva + * + */ + +static drm_intel_bufmgr *bufmgr; +struct intel_batchbuffer *batch; + +uint32_t blob[2048*2048]; +#define NUM_TARGET_BOS 16 +drm_intel_bo *pc_target_bo[NUM_TARGET_BOS]; +drm_intel_bo *dummy_bo; +drm_intel_bo *special_bos[NUM_TARGET_BOS]; +uint32_t relocs_bo_handle[NUM_TARGET_BOS]; +void *gtt_relocs_ptr[NUM_TARGET_BOS]; +uint32_t devid; +int special_reloc_ofs; +int special_line_ofs; +int special_batch_len; + +int small_pitch = 64; + +static drm_intel_bo *create_special_bo(void) +{ + drm_intel_bo *bo; + uint32_t data[1024]; + int len = 0; +#define BATCH(dw) data[len++] = (dw); + + memset(data, 0, 4096); + bo = drm_intel_bo_alloc(bufmgr, "special batch", 4096, 4096); + + if (intel_gen(devid) >= 8) { + BATCH(MI_NOOP); + BATCH(XY_COLOR_BLT_CMD_NOLEN | 5 | + COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB); + } else { + BATCH(XY_COLOR_BLT_CMD_NOLEN | 4 | + COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB); + } + + BATCH((3 << 24) | (0xf0 << 16) | small_pitch); + special_line_ofs = 4*len; + BATCH(0); + BATCH(1 << 16 | 1); + special_reloc_ofs = 4*len; + BATCH(0); + if (intel_gen(devid) >= 8) + BATCH(0); /* FIXME */ + BATCH(0xdeadbeef); + +#define CMD_POLY_STIPPLE_OFFSET 0x7906 + /* batchbuffer end */ + if (IS_GEN5(batch->devid)) { + BATCH(CMD_POLY_STIPPLE_OFFSET << 16); + BATCH(0); + } + igt_assert(len % 2 == 0); + BATCH(MI_NOOP); + BATCH(MI_BATCH_BUFFER_END); + + drm_intel_bo_subdata(bo, 0, 4096, data); + special_batch_len = len*4; + + return bo; +} + +static void emit_dummy_load(int pitch) +{ + int i; + uint32_t tile_flags = 0; + + if (IS_965(devid)) { + pitch /= 4; + tile_flags = XY_SRC_COPY_BLT_SRC_TILED | + XY_SRC_COPY_BLT_DST_TILED; + } + + for (i = 0; i < 5; i++) { + BLIT_COPY_BATCH_START(devid, tile_flags); + OUT_BATCH((3 << 24) | /* 32 bits */ + (0xcc << 16) | /* copy ROP */ + pitch); + OUT_BATCH(0 << 16 | 1024); + OUT_BATCH((2048) << 16 | (2048)); + OUT_RELOC_FENCED(dummy_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(devid); + OUT_BATCH(0 << 16 | 0); + OUT_BATCH(pitch); + OUT_RELOC_FENCED(dummy_bo, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(devid); + ADVANCE_BATCH(); + + if (intel_gen(devid) >= 6) { + BEGIN_BATCH(3); + OUT_BATCH(XY_SETUP_CLIP_BLT_CMD); + OUT_BATCH(0); + OUT_BATCH(0); + ADVANCE_BATCH(); + } + } + intel_batchbuffer_flush(batch); +} + +static void faulting_reloc_and_emit(int fd, drm_intel_bo *target_bo, + void *gtt_relocs, drm_intel_bo *special_bo) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 exec[2]; + int ring; + + if (intel_gen(devid) >= 6) + ring = I915_EXEC_BLT; + else + ring = 0; + + exec[0].handle = target_bo->handle; + exec[0].relocation_count = 0; + exec[0].relocs_ptr = 0; + exec[0].alignment = 0; + exec[0].offset = 0; + exec[0].flags = 0; + exec[0].rsvd1 = 0; + exec[0].rsvd2 = 0; + + exec[1].handle = special_bo->handle; + exec[1].relocation_count = 1; + /* A newly mmap gtt bo will fault on first access. */ + exec[1].relocs_ptr = (uintptr_t)gtt_relocs; + exec[1].alignment = 0; + exec[1].offset = 0; + exec[1].flags = 0; + exec[1].rsvd1 = 0; + exec[1].rsvd2 = 0; + + execbuf.buffers_ptr = (uintptr_t)exec; + execbuf.buffer_count = 2; + execbuf.batch_start_offset = 0; + execbuf.batch_len = special_batch_len; + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = ring; + i915_execbuffer2_set_context_id(execbuf, 0); + execbuf.rsvd2 = 0; + + gem_execbuf(fd, &execbuf); +} + +static void do_test(int fd, bool faulting_reloc) +{ + uint32_t tiling_mode = I915_TILING_X; + unsigned long pitch, act_size; + uint32_t test; + int i, repeat; + + if (faulting_reloc) + igt_disable_prefault(); + + act_size = 2048; + dummy_bo = drm_intel_bo_alloc_tiled(bufmgr, "tiled dummy_bo", act_size, act_size, + 4, &tiling_mode, &pitch, 0); + + drm_intel_bo_subdata(dummy_bo, 0, act_size*act_size*4, blob); + + for (i = 0; i < NUM_TARGET_BOS; i++) { + struct drm_i915_gem_relocation_entry reloc[1]; + + special_bos[i] = create_special_bo(); + pc_target_bo[i] = drm_intel_bo_alloc(bufmgr, "special batch", 4096, 4096); + igt_assert(pc_target_bo[i]->offset == 0); + + reloc[0].offset = special_reloc_ofs; + reloc[0].delta = 0; + reloc[0].target_handle = pc_target_bo[i]->handle; + reloc[0].read_domains = I915_GEM_DOMAIN_RENDER; + reloc[0].write_domain = I915_GEM_DOMAIN_RENDER; + reloc[0].presumed_offset = 0; + + relocs_bo_handle[i] = gem_create(fd, 4096); + gem_write(fd, relocs_bo_handle[i], 0, reloc, sizeof(reloc)); + gtt_relocs_ptr[i] = gem_mmap(fd, relocs_bo_handle[i], 4096, + PROT_READ | PROT_WRITE); + igt_assert(gtt_relocs_ptr[i]); + + } + + /* repeat must be smaller than 4096/small_pitch */ + for (repeat = 0; repeat < 8; repeat++) { + for (i = 0; i < NUM_TARGET_BOS; i++) { + uint32_t data[2] = { + (repeat << 16) | 0, + ((repeat + 1) << 16) | 1 + }; + + drm_intel_bo_subdata(special_bos[i], special_line_ofs, 8, &data); + + emit_dummy_load(pitch); + faulting_reloc_and_emit(fd, pc_target_bo[i], + gtt_relocs_ptr[i], + special_bos[i]); + } + } + + /* Only check at the end to avoid unnecessarily synchronous behaviour. */ + for (i = 0; i < NUM_TARGET_BOS; i++) { + /* repeat must be smaller than 4096/small_pitch */ + for (repeat = 0; repeat < 8; repeat++) { + drm_intel_bo_get_subdata(pc_target_bo[i], + repeat*small_pitch, 4, &test); + igt_assert_f(test == 0xdeadbeef, + "mismatch in buffer %i: 0x%08x instead of 0xdeadbeef at offset %i\n", + i, test, repeat*small_pitch); + } + drm_intel_bo_unreference(pc_target_bo[i]); + drm_intel_bo_unreference(special_bos[i]); + gem_close(fd, relocs_bo_handle[i]); + munmap(gtt_relocs_ptr[i], 4096); + } + + drm_intel_gem_bo_map_gtt(dummy_bo); + drm_intel_gem_bo_unmap_gtt(dummy_bo); + + drm_intel_bo_unreference(dummy_bo); + + if (faulting_reloc) + igt_enable_prefault(); +} + +#define INTERRUPT (1 << 0) +#define FAULTING (1 << 1) +#define THRASH (1 << 2) +#define THRASH_INACTIVE (1 << 3) +#define ALL_FLAGS (INTERRUPT | FAULTING | THRASH | THRASH_INACTIVE) +static void do_forked_test(int fd, unsigned flags) +{ + int num_threads = sysconf(_SC_NPROCESSORS_ONLN); + struct igt_helper_process thrasher = {}; + + if (flags & (THRASH | THRASH_INACTIVE)) { + uint64_t val = (flags & THRASH_INACTIVE) ? + (DROP_RETIRE | DROP_BOUND | DROP_UNBOUND) : DROP_ALL; + + igt_fork_helper(&thrasher) { + while (1) { + usleep(1000); + igt_drop_caches_set(val); + } + } + } + + igt_fork(i, num_threads) { + /* re-create process local data */ + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + batch = intel_batchbuffer_alloc(bufmgr, devid); + + if (flags & INTERRUPT) + igt_fork_signal_helper(); + + do_test(fd, flags & FAULTING); + + if (flags & INTERRUPT) + igt_stop_signal_helper(); + } + + igt_waitchildren(); + if (flags & (THRASH | THRASH_INACTIVE)) + igt_stop_helper(&thrasher); +} + +int fd; + +#define MAX_BLT_SIZE 128 +igt_main +{ + igt_skip_on_simulation(); + + memset(blob, 'A', sizeof(blob)); + + igt_fixture { + fd = drm_open_any(); + + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + /* disable reuse, otherwise the test fails */ + //drm_intel_bufmgr_gem_enable_reuse(bufmgr); + devid = intel_get_drm_devid(fd); + batch = intel_batchbuffer_alloc(bufmgr, devid); + } + + igt_subtest("normal") + do_test(fd, false); + + igt_fork_signal_helper(); + igt_subtest("interruptible") + do_test(fd, false); + igt_stop_signal_helper(); + + for (unsigned flags = 0; flags <= ALL_FLAGS; flags++) { + if ((flags & THRASH) && (flags & THRASH_INACTIVE)) + continue; + + igt_subtest_f("forked%s%s%s%s", + flags & INTERRUPT ? "-interruptible" : "", + flags & FAULTING ? "-faulting-reloc" : "", + flags & THRASH ? "-thrashing" : "", + flags & THRASH_INACTIVE ? "-thrash-inactive" : "") + do_forked_test(fd, flags); + } + + igt_fixture { + intel_batchbuffer_free(batch); + drm_intel_bufmgr_destroy(bufmgr); + + close(fd); + } +} diff --git a/tests/gem_pin.c b/tests/gem_pin.c new file mode 100644 index 00000000..91e1456a --- /dev/null +++ b/tests/gem_pin.c @@ -0,0 +1,250 @@ +/* + * Copyright © 20013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Chris Wilson <chris@chris-wilson.co.uk> + * + */ + +/* Exercises pinning of small bo */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> + +#include <drm.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_chipset.h" +#include "intel_io.h" +#include "igt_aux.h" + +#define COPY_BLT_CMD (2<<29|0x53<<22|0x6) +#define BLT_WRITE_ALPHA (1<<21) +#define BLT_WRITE_RGB (1<<20) + +static void exec(int fd, uint32_t handle, uint32_t offset) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 gem_exec[1]; + struct drm_i915_gem_relocation_entry gem_reloc[1]; + + gem_reloc[0].offset = 1024; + gem_reloc[0].delta = 0; + gem_reloc[0].target_handle = handle; + gem_reloc[0].read_domains = I915_GEM_DOMAIN_RENDER; + gem_reloc[0].write_domain = 0; + gem_reloc[0].presumed_offset = 0; + + gem_exec[0].handle = handle; + gem_exec[0].relocation_count = 1; + gem_exec[0].relocs_ptr = (uintptr_t) gem_reloc; + gem_exec[0].alignment = 0; + gem_exec[0].offset = 0; + gem_exec[0].flags = 0; + gem_exec[0].rsvd1 = 0; + gem_exec[0].rsvd2 = 0; + + execbuf.buffers_ptr = (uintptr_t)gem_exec; + execbuf.buffer_count = 1; + execbuf.batch_start_offset = 0; + execbuf.batch_len = 8; + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = 0; + i915_execbuffer2_set_context_id(execbuf, 0); + execbuf.rsvd2 = 0; + + do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf)); + igt_assert(gem_exec[0].offset == offset); +} + +static int gem_linear_blt(int fd, + uint32_t *batch, + uint32_t src, + uint32_t dst, + uint32_t length, + struct drm_i915_gem_relocation_entry *reloc) +{ + uint32_t *b = batch; + + *b++ = COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB; + *b++ = 0x66 << 16 | 1 << 25 | 1 << 24 | (4*1024); + *b++ = 0; + *b++ = (length / (4*1024)) << 16 | 1024; + *b++ = 0; + reloc->offset = (b-batch-1) * sizeof(uint32_t); + reloc->delta = 0; + reloc->target_handle = dst; + reloc->read_domains = I915_GEM_DOMAIN_RENDER; + reloc->write_domain = I915_GEM_DOMAIN_RENDER; + reloc->presumed_offset = 0; + reloc++; + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + *b++ = 0; /* FIXME */ + + *b++ = 0; + *b++ = 4*1024; + *b++ = 0; + reloc->offset = (b-batch-1) * sizeof(uint32_t); + reloc->delta = 0; + reloc->target_handle = src; + reloc->read_domains = I915_GEM_DOMAIN_RENDER; + reloc->write_domain = 0; + reloc->presumed_offset = 0; + reloc++; + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + *b++ = 0; /* FIXME */ + + *b++ = MI_BATCH_BUFFER_END; + *b++ = 0; + + return (b - batch) * sizeof(uint32_t); +} + +static void make_busy(int fd, uint32_t handle) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 obj[2]; + struct drm_i915_gem_relocation_entry reloc[2]; + uint32_t batch[20]; + uint32_t tmp; + int count; + + tmp = gem_create(fd, 1024*1024); + + obj[0].handle = tmp; + obj[0].relocation_count = 0; + obj[0].relocs_ptr = 0; + obj[0].alignment = 0; + obj[0].offset = 0; + obj[0].flags = 0; + obj[0].rsvd1 = 0; + obj[0].rsvd2 = 0; + + obj[1].handle = handle; + obj[1].relocation_count = 2; + obj[1].relocs_ptr = (uintptr_t) reloc; + obj[1].alignment = 0; + obj[1].offset = 0; + obj[1].flags = 0; + obj[1].rsvd1 = 0; + obj[1].rsvd2 = 0; + + execbuf.buffers_ptr = (uintptr_t)obj; + execbuf.buffer_count = 2; + execbuf.batch_start_offset = 0; + execbuf.batch_len = gem_linear_blt(fd, batch, tmp, tmp, 1024*1024,reloc); + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = 0; + if (HAS_BLT_RING(intel_get_drm_devid(fd))) + execbuf.flags |= I915_EXEC_BLT; + i915_execbuffer2_set_context_id(execbuf, 0); + execbuf.rsvd2 = 0; + + gem_write(fd, handle, 0, batch, execbuf.batch_len); + for (count = 0; count < 10; count++) + do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf)); + gem_close(fd, tmp); +} + +static int test_can_pin(int fd) +{ + struct drm_i915_gem_pin pin; + int ret; + + pin.handle = gem_create(fd, 4096);; + pin.alignment = 0; + ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_PIN, &pin); + gem_close(fd, pin.handle); + + return ret == 0;; +} + +static uint32_t gem_pin(int fd, int handle, int alignment) +{ + struct drm_i915_gem_pin pin; + + pin.handle = handle; + pin.alignment = alignment; + do_ioctl(fd, DRM_IOCTL_I915_GEM_PIN, &pin); + return pin.offset; +} + +igt_simple_main +{ + const uint32_t batch[2] = {MI_BATCH_BUFFER_END}; + struct timeval start, now; + uint32_t *handle, *offset; + int fd, i; + + igt_skip_on_simulation(); + + fd = drm_open_any(); + + igt_require(test_can_pin(fd)); + + handle = malloc(sizeof(uint32_t)*100); + offset = malloc(sizeof(uint32_t)*100); + + /* Race creation/use against interrupts */ + igt_fork_signal_helper(); + gettimeofday(&start, NULL); + do { + for (i = 0; i < 100; i++) { + if (i & 1) { + /* pin anidle bo */ + handle[i] = gem_create(fd, 4096); + offset[i] = gem_pin(fd, handle[i], 0); + igt_assert(offset[i]); + gem_write(fd, handle[i], 0, batch, sizeof(batch)); + } else { + /* try to pin an anidle bo */ + handle[i] = gem_create(fd, 4096); + make_busy(fd, handle[i]); + offset[i] = gem_pin(fd, handle[i], 256*1024); + igt_assert(offset[i]); + igt_assert((offset[i] & (256*1024-1)) == 0); + gem_write(fd, handle[i], 0, batch, sizeof(batch)); + } + } + for (i = 0; i < 1000; i++) { + int j = rand() % 100; + exec(fd, handle[j], offset[j]); + } + for (i = 0; i < 100; i++) + gem_close(fd, handle[i]); + gettimeofday(&now, NULL); + } while ((now.tv_sec - start.tv_sec)*1000 + (now.tv_usec - start.tv_usec) / 1000 < 10000); + igt_stop_signal_helper(); +} diff --git a/tests/gem_pipe_control_store_loop.c b/tests/gem_pipe_control_store_loop.c index e03cddd7..c95c2bdf 100644 --- a/tests/gem_pipe_control_store_loop.c +++ b/tests/gem_pipe_control_store_loop.c @@ -34,18 +34,18 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_chipset.h" +#include "intel_io.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; @@ -64,25 +64,54 @@ uint32_t devid; /* Like the store dword test, but we create new command buffers each time */ static void -store_pipe_control_loop(void) +store_pipe_control_loop(bool preuse_buffer) { int i, val = 0; uint32_t *buf; drm_intel_bo *target_bo; - for (i = 0; i < 0x10000; i++) { + for (i = 0; i < SLOW_QUICK(0x10000, 4); i++) { /* we want to check tlb consistency of the pipe_control target, * so get a new buffer every time around */ target_bo = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096); - if (!target_bo) { - fprintf(stderr, "failed to alloc target buffer\n"); - exit(-1); + igt_assert(target_bo); + + if (preuse_buffer) { + COLOR_BLIT_COPY_BATCH_START(devid, 0); + OUT_BATCH((3 << 24) | (0xf0 << 16) | 64); + OUT_BATCH(0); + OUT_BATCH(1 << 16 | 1); + + /* + * IMPORTANT: We need to preuse the buffer in a + * different domain than what the pipe control write + * (and kernel wa) uses! + */ + OUT_RELOC(target_bo, + I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, + 0); + BLIT_RELOC_UDW(devid); + OUT_BATCH(0xdeadbeef); + ADVANCE_BATCH(); + + intel_batchbuffer_flush(batch); } /* gem_storedw_batches_loop.c is a bit overenthusiastic with * creating new batchbuffers - with buffer reuse disabled, the * support code will do that for us. */ - if (intel_gen(devid) >= 6) { + if (intel_gen(devid) >= 8) { + BEGIN_BATCH(5); + OUT_BATCH(GFX_OP_PIPE_CONTROL + 1); + OUT_BATCH(PIPE_CONTROL_WRITE_IMMEDIATE); + OUT_RELOC(target_bo, + I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, + PIPE_CONTROL_GLOBAL_GTT); + BLIT_RELOC_UDW(devid); + OUT_BATCH(val); /* write data */ + ADVANCE_BATCH(); + + } else if (intel_gen(devid) >= 6) { /* work-around hw issue, see intel_emit_post_sync_nonzero_flush * in mesa sources. */ BEGIN_BATCH(4); @@ -119,66 +148,50 @@ store_pipe_control_loop(void) drm_intel_bo_map(target_bo, 1); buf = target_bo->virtual; - if (buf[0] != val) { - fprintf(stderr, - "value mismatch: cur 0x%08x, stored 0x%08x\n", - buf[0], val); - exit(-1); - } - buf[0] = 0; /* let batch write it again */ - drm_intel_bo_unmap(target_bo); + igt_assert(buf[0] == val); + drm_intel_bo_unmap(target_bo); + /* Make doublesure that this buffer won't get reused. */ + drm_intel_bo_disable_reuse(target_bo); drm_intel_bo_unreference(target_bo); val++; } - - printf("completed %d writes successfully\n", i); } -int main(int argc, char **argv) +int fd; + +igt_main { - int fd; + igt_fixture { + fd = drm_open_any(); + devid = intel_get_drm_devid(fd); - if (argc != 1) { - fprintf(stderr, "usage: %s\n", argv[0]); - exit(-1); - } + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + igt_assert(bufmgr); - fd = drm_open_any(); - devid = intel_get_drm_devid(fd); + igt_skip_on(IS_GEN2(devid) || IS_GEN3(devid)); + igt_skip_on(devid == PCI_CHIP_I965_G); /* has totally broken pipe control */ - bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - if (!bufmgr) { - fprintf(stderr, "failed to init libdrm\n"); - exit(-1); - } + /* IMPORTANT: No call to + * drm_intel_bufmgr_gem_enable_reuse(bufmgr); + * here because we wan't to have fresh buffers (to trash the tlb) + * every time! */ - if (IS_GEN2(devid) || IS_GEN3(devid)) { - fprintf(stderr, "no pipe_control on gen2/3\n"); - return 77; - } - if (devid == PCI_CHIP_I965_G) { - fprintf(stderr, "pipe_control totally broken on i965\n"); - return 77; - } - /* IMPORTANT: No call to - * drm_intel_bufmgr_gem_enable_reuse(bufmgr); - * here because we wan't to have fresh buffers (to trash the tlb) - * every time! */ - - batch = intel_batchbuffer_alloc(bufmgr, devid); - if (!batch) { - fprintf(stderr, "failed to create batch buffer\n"); - exit(-1); + batch = intel_batchbuffer_alloc(bufmgr, devid); + igt_assert(batch); } - store_pipe_control_loop(); + igt_subtest("fresh-buffer") + store_pipe_control_loop(false); - intel_batchbuffer_free(batch); - drm_intel_bufmgr_destroy(bufmgr); + igt_subtest("reused-buffer") + store_pipe_control_loop(true); - close(fd); + igt_fixture { + intel_batchbuffer_free(batch); + drm_intel_bufmgr_destroy(bufmgr); - return 0; + close(fd); + } } diff --git a/tests/gem_pread.c b/tests/gem_pread.c new file mode 100644 index 00000000..cc83948b --- /dev/null +++ b/tests/gem_pread.c @@ -0,0 +1,153 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Chris Wilson <chris@chris-wilson.co.uk> + * + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include "drm.h" +#include "ioctl_wrappers.h" +#include "drmtest.h" + +#define OBJECT_SIZE 16384 + +static void do_gem_read(int fd, uint32_t handle, void *buf, int len, int loops) +{ + while (loops--) + gem_read(fd, handle, 0, buf, len); +} + +static double elapsed(const struct timeval *start, + const struct timeval *end, + int loop) +{ + return (1e6*(end->tv_sec - start->tv_sec) + (end->tv_usec - start->tv_usec))/loop; +} + +static const char *bytes_per_sec(char *buf, double v) +{ + const char *order[] = { + "", + "KiB", + "MiB", + "GiB", + "TiB", + NULL, + }, **o = order; + + while (v > 1000 && o[1]) { + v /= 1000; + o++; + } + sprintf(buf, "%.1f%s/s", v, *o); + return buf; +} + + +uint32_t *src, dst; +int fd, count; + +int main(int argc, char **argv) +{ + int object_size = 0; + uint32_t buf[20]; + const struct { + int level; + const char *name; + } cache[] = { + { 0, "uncached" }, + { 1, "snoop" }, + { 2, "display" }, + { -1 }, + }, *c; + + igt_subtest_init(argc, argv); + igt_skip_on_simulation(); + + if (argc > 1 && atoi(argv[1])) + object_size = atoi(argv[1]); + if (object_size == 0) + object_size = OBJECT_SIZE; + object_size = (object_size + 3) & -4; + + igt_fixture { + fd = drm_open_any(); + + dst = gem_create(fd, object_size); + src = malloc(object_size); + } + + igt_subtest("normal") { + for (count = 1; count <= 1<<17; count <<= 1) { + struct timeval start, end; + + gettimeofday(&start, NULL); + do_gem_read(fd, dst, src, object_size, count); + gettimeofday(&end, NULL); + igt_info("Time to pread %d bytes x %6d: %7.3fµs, %s\n", + object_size, count, + elapsed(&start, &end, count), + bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6)); + fflush(stdout); + } + } + + for (c = cache; c->level != -1; c++) { + igt_subtest(c->name) { + gem_set_caching(fd, dst, c->level); + + for (count = 1; count <= 1<<17; count <<= 1) { + struct timeval start, end; + + gettimeofday(&start, NULL); + do_gem_read(fd, dst, src, object_size, count); + gettimeofday(&end, NULL); + igt_info("Time to %s pread %d bytes x %6d: %7.3fµs, %s\n", + c->name, object_size, count, + elapsed(&start, &end, count), + bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6)); + fflush(stdout); + } + } + } + + igt_fixture { + free(src); + gem_close(fd, dst); + + close(fd); + } + + igt_exit(); +} diff --git a/tests/gem_pread_after_blit.c b/tests/gem_pread_after_blit.c index c9c8b02c..0b8bfa6c 100644 --- a/tests/gem_pread_after_blit.c +++ b/tests/gem_pread_after_blit.c @@ -37,18 +37,19 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> -#include "drm.h" -#include "i915_drm.h" + +#include <drm.h> + +#include "ioctl_wrappers.h" #include "drmtest.h" -#include "intel_bufmgr.h" -#include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_chipset.h" +#include "intel_io.h" +#include "igt_aux.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; @@ -87,13 +88,10 @@ verify_large_read(drm_intel_bo *bo, uint32_t val) drm_intel_bo_get_subdata(bo, 0, size, buf); for (i = 0; i < size / 4; i++) { - if (buf[i] != val) { - fprintf(stderr, - "Unexpected value 0x%08x instead of " - "0x%08x at offset 0x%08x (%p)\n", - buf[i], val, i * 4, buf); - abort(); - } + igt_assert_f(buf[i] == val, + "Unexpected value 0x%08x instead of " + "0x%08x at offset 0x%08x (%p)\n", + buf[i], val, i * 4, buf); val++; } } @@ -112,64 +110,126 @@ verify_small_read(drm_intel_bo *bo, uint32_t val) drm_intel_bo_get_subdata(bo, offset, PAGE_SIZE, buf); for (i = 0; i < PAGE_SIZE; i += 4) { - if (buf[i / 4] != val) { - fprintf(stderr, - "Unexpected value 0x%08x instead of " - "0x%08x at offset 0x%08x\n", - buf[i / 4], val, i * 4); - abort(); - } + igt_assert_f(buf[i / 4] == val, + "Unexpected value 0x%08x instead of " + "0x%08x at offset 0x%08x\n", + buf[i / 4], val, i * 4); val++; } } } -int -main(int argc, char **argv) +static void do_test(int fd, int cache_level, + drm_intel_bo *src[2], + const uint32_t start[2], + drm_intel_bo *tmp[2], + int loop) { - int fd; - drm_intel_bo *src1, *src2, *bo; - uint32_t start1 = 0; - uint32_t start2 = 1024 * 1024 / 4; + if (cache_level != -1) { + gem_set_caching(fd, tmp[0]->handle, cache_level); + gem_set_caching(fd, tmp[1]->handle, cache_level); + } - fd = drm_open_any(); + do { + /* First, do a full-buffer read after blitting */ + intel_copy_bo(batch, tmp[0], src[0], width*height*4); + verify_large_read(tmp[0], start[0]); + intel_copy_bo(batch, tmp[0], src[1], width*height*4); + verify_large_read(tmp[0], start[1]); + + intel_copy_bo(batch, tmp[0], src[0], width*height*4); + verify_small_read(tmp[0], start[0]); + intel_copy_bo(batch, tmp[0], src[1], width*height*4); + verify_small_read(tmp[0], start[1]); + + intel_copy_bo(batch, tmp[0], src[0], width*height*4); + verify_large_read(tmp[0], start[0]); + + intel_copy_bo(batch, tmp[0], src[0], width*height*4); + intel_copy_bo(batch, tmp[1], src[1], width*height*4); + verify_large_read(tmp[0], start[0]); + verify_large_read(tmp[1], start[1]); + + intel_copy_bo(batch, tmp[0], src[0], width*height*4); + intel_copy_bo(batch, tmp[1], src[1], width*height*4); + verify_large_read(tmp[1], start[1]); + verify_large_read(tmp[0], start[0]); + + intel_copy_bo(batch, tmp[1], src[0], width*height*4); + intel_copy_bo(batch, tmp[0], src[1], width*height*4); + verify_large_read(tmp[0], start[1]); + verify_large_read(tmp[1], start[0]); + } while (--loop); +} - bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - drm_intel_bufmgr_gem_enable_reuse(bufmgr); - batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); +drm_intel_bo *src[2], *dst[2]; +int fd; - src1 = create_bo(start1); - src2 = create_bo(start2); +igt_main +{ + const uint32_t start[2] = {0, 1024 * 1024 / 4}; - bo = drm_intel_bo_alloc(bufmgr, "dst bo", size, 4096); + igt_skip_on_simulation(); - /* First, do a full-buffer read after blitting */ - printf("Large read after blit 1\n"); - intel_copy_bo(batch, bo, src1, width, height); - verify_large_read(bo, start1); - printf("Large read after blit 2\n"); - intel_copy_bo(batch, bo, src2, width, height); - verify_large_read(bo, start2); + igt_fixture { + fd = drm_open_any(); - printf("Small reads after blit 1\n"); - intel_copy_bo(batch, bo, src1, width, height); - verify_small_read(bo, start1); - printf("Small reads after blit 2\n"); - intel_copy_bo(batch, bo, src2, width, height); - verify_small_read(bo, start2); + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + drm_intel_bufmgr_gem_enable_reuse(bufmgr); + batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); - printf("Large read after blit 3\n"); - intel_copy_bo(batch, bo, src1, width, height); - verify_large_read(bo, start1); + src[0] = create_bo(start[0]); + src[1] = create_bo(start[1]); - drm_intel_bo_unreference(src1); - drm_intel_bo_unreference(src2); - drm_intel_bo_unreference(bo); + dst[0] = drm_intel_bo_alloc(bufmgr, "dst bo", size, 4096); + dst[1] = drm_intel_bo_alloc(bufmgr, "dst bo", size, 4096); + } - intel_batchbuffer_free(batch); - drm_intel_bufmgr_destroy(bufmgr); + igt_subtest("normal") + do_test(fd, -1, src, start, dst, 1); - close(fd); + igt_subtest("interruptible") { + igt_fork_signal_helper(); + do_test(fd, -1, src, start, dst, 100); + igt_stop_signal_helper(); + } + + igt_subtest("normal-uncached") + do_test(fd, 0, src, start, dst, 1); + + igt_subtest("interruptible-uncached") { + igt_fork_signal_helper(); + do_test(fd, 0, src, start, dst, 100); + igt_stop_signal_helper(); + } + + igt_subtest("normal-snoop") + do_test(fd, 1, src, start, dst, 1); + + igt_subtest("interruptible-snoop") { + igt_fork_signal_helper(); + do_test(fd, 1, src, start, dst, 100); + igt_stop_signal_helper(); + } + + igt_subtest("normal-display") + do_test(fd, 2, src, start, dst, 1); - return 0; + igt_subtest("interruptible-display") { + igt_fork_signal_helper(); + do_test(fd, 2, src, start, dst, 100); + igt_stop_signal_helper(); + } + + igt_fixture { + drm_intel_bo_unreference(src[0]); + drm_intel_bo_unreference(src[1]); + drm_intel_bo_unreference(dst[0]); + drm_intel_bo_unreference(dst[1]); + + intel_batchbuffer_free(batch); + drm_intel_bufmgr_destroy(bufmgr); + } + + close(fd); } diff --git a/tests/gem_pwrite.c b/tests/gem_pwrite.c index 051ed3b5..6378b0a4 100644 --- a/tests/gem_pwrite.c +++ b/tests/gem_pwrite.c @@ -30,16 +30,14 @@ #include <stdint.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/ioctl.h> -#include <sys/mman.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #define OBJECT_SIZE 16384 @@ -49,7 +47,6 @@ #define BLT_WRITE_RGB (1<<20) #define BLT_SRC_TILED (1<<15) #define BLT_DST_TILED (1<<11) -#define MI_BATCH_BUFFER_END (0xA<<23) static void do_gem_write(int fd, uint32_t handle, void *buf, int len, int loops) { @@ -84,39 +81,81 @@ static const char *bytes_per_sec(char *buf, double v) } +uint32_t *src, dst; +int fd; + int main(int argc, char **argv) { int object_size = 0; uint32_t buf[20]; - uint32_t *src, dst; - int fd, count; + int count; + const struct { + int level; + const char *name; + } cache[] = { + { 0, "uncached" }, + { 1, "snoop" }, + { 2, "display" }, + { -1 }, + }, *c; + + igt_skip_on_simulation(); - if (argc > 1) + igt_subtest_init(argc, argv); + + if (argc > 1 && atoi(argv[1])) object_size = atoi(argv[1]); if (object_size == 0) object_size = OBJECT_SIZE; object_size = (object_size + 3) & -4; - fd = drm_open_any(); - - dst = gem_create(fd, object_size); - src = malloc(object_size); - for (count = 1; count <= 1<<17; count <<= 1) { - struct timeval start, end; - - gettimeofday(&start, NULL); - do_gem_write(fd, dst, src, object_size, count); - gettimeofday(&end, NULL); - printf("Time to pwrite %d bytes x %6d: %7.3fµs, %s\n", - object_size, count, - elapsed(&start, &end, count), - bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6)); - fflush(stdout); + igt_fixture { + fd = drm_open_any(); + + dst = gem_create(fd, object_size); + src = malloc(object_size); + } + + igt_subtest("normal") { + for (count = 1; count <= 1<<17; count <<= 1) { + struct timeval start, end; + + gettimeofday(&start, NULL); + do_gem_write(fd, dst, src, object_size, count); + gettimeofday(&end, NULL); + igt_info("Time to pwrite %d bytes x %6d: %7.3fµs, %s\n", + object_size, count, + elapsed(&start, &end, count), + bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6)); + fflush(stdout); + } } - free(src); - gem_close(fd, dst); - close(fd); + for (c = cache; c->level != -1; c++) { + igt_subtest(c->name) { + gem_set_caching(fd, dst, c->level); + + for (count = 1; count <= 1<<17; count <<= 1) { + struct timeval start, end; + + gettimeofday(&start, NULL); + do_gem_write(fd, dst, src, object_size, count); + gettimeofday(&end, NULL); + igt_info("Time to %s pwrite %d bytes x %6d: %7.3fµs, %s\n", + c->name, object_size, count, + elapsed(&start, &end, count), + bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6)); + fflush(stdout); + } + } + } + + igt_fixture { + free(src); + gem_close(fd, dst); + + close(fd); + } - return 0; + igt_exit(); } diff --git a/tests/gem_pwrite_pread.c b/tests/gem_pwrite_pread.c new file mode 100644 index 00000000..c2dc74b7 --- /dev/null +++ b/tests/gem_pwrite_pread.c @@ -0,0 +1,413 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Chris Wilson <chris@chris-wilson.co.uk> + * + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include "drm.h" +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_chipset.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_io.h" + +#define OBJECT_SIZE 16384 + +#define COPY_BLT_CMD (2<<29|0x53<<22) +#define BLT_WRITE_ALPHA (1<<21) +#define BLT_WRITE_RGB (1<<20) +#define BLT_SRC_TILED (1<<15) +#define BLT_DST_TILED (1<<11) + +uint32_t is_64bit; +uint32_t exec_flags; + +static inline void build_batch(uint32_t *batch, int len, uint32_t *batch_len) +{ + unsigned int i = 0; + + batch[i++] = COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB | (is_64bit ? 8 : 6); + batch[i++] = 0xcc << 16 | 1 << 25 | 1 << 24 | len; + batch[i++] = 0; + batch[i++] = 1 << 16 | (len / 4); + batch[i++] = 0; /* dst */ + if (is_64bit) + batch[i++] = 0; + batch[i++] = 0; + batch[i++] = len; + batch[i++] = 0; /* src */ + if (is_64bit) + batch[i++] = 0; + batch[i++] = MI_BATCH_BUFFER_END; + batch[i++] = 0; + + *batch_len = i * 4; +} + +#define BUILD_EXEC \ + uint32_t batch[12]; \ + struct drm_i915_gem_relocation_entry reloc[] = { \ + { dst, 0, 4*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER }, \ + { src, 0, (is_64bit ? 8 : 7)*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, 0 }, \ + }; \ + struct drm_i915_gem_exec_object2 exec[] = { \ + { src }, \ + { dst }, \ + { gem_create(fd, 4096), 2, (uintptr_t)reloc } \ + }; \ + struct drm_i915_gem_execbuffer2 execbuf = { \ + (uintptr_t)exec, 3, \ + 0, 0, \ + 0, 0, 0, 0, \ + exec_flags, \ + }; \ + build_batch(batch, len, &execbuf.batch_len); \ + gem_write(fd, exec[2].handle, 0, batch, execbuf.batch_len); + + +static void copy(int fd, uint32_t src, uint32_t dst, void *buf, int len, int loops) +{ + BUILD_EXEC; + + while (loops--) { + gem_write(fd, src, 0, buf, len); + do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf)); + gem_read(fd, dst, 0, buf, len); + } + + gem_close(fd, exec[2].handle); +} + +static void as_gtt_mmap(int fd, uint32_t src, uint32_t dst, void *buf, int len, int loops) +{ + uint32_t *src_ptr, *dst_ptr; + BUILD_EXEC; + + src_ptr = gem_mmap__gtt(fd, src, OBJECT_SIZE, PROT_WRITE); + dst_ptr = gem_mmap__gtt(fd, dst, OBJECT_SIZE, PROT_READ); + + while (loops--) { + gem_set_domain(fd, src, + I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); + memcpy(src_ptr, buf, len); + + do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf)); + gem_set_domain(fd, dst, + I915_GEM_DOMAIN_GTT, 0); + memcpy(buf, dst_ptr, len); + } + + munmap(dst_ptr, len); + munmap(src_ptr, len); + gem_close(fd, exec[2].handle); +} + + +static void as_cpu_mmap(int fd, uint32_t src, uint32_t dst, void *buf, int len, int loops) +{ + uint32_t *src_ptr, *dst_ptr; + BUILD_EXEC; + + src_ptr = gem_mmap__cpu(fd, src, OBJECT_SIZE, PROT_WRITE); + dst_ptr = gem_mmap__cpu(fd, dst, OBJECT_SIZE, PROT_READ); + + while (loops--) { + gem_set_domain(fd, src, + I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); + memcpy(src_ptr, buf, len); + + do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf)); + gem_set_domain(fd, dst, + I915_GEM_DOMAIN_CPU, 0); + memcpy(buf, dst_ptr, len); + } + + munmap(dst_ptr, len); + munmap(src_ptr, len); + gem_close(fd, exec[2].handle); +} + +static void test_copy(int fd, uint32_t src, uint32_t dst, uint32_t *buf, int len) +{ + int i; + BUILD_EXEC; + + for (i = 0; i < len/4; i++) + buf[i] = i; + + gem_write(fd, src, 0, buf, len); + memset(buf, 0, len); + + do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf)); + gem_read(fd, dst, 0, buf, len); + + gem_close(fd, exec[2].handle); + + for (i = 0; i < len/4; i++) + igt_assert(buf[i] == i); +} + +static void test_as_gtt_mmap(int fd, uint32_t src, uint32_t dst, int len) +{ + uint32_t *src_ptr, *dst_ptr; + int i; + BUILD_EXEC; + + src_ptr = gem_mmap__gtt(fd, src, OBJECT_SIZE, PROT_WRITE); + dst_ptr = gem_mmap__gtt(fd, dst, OBJECT_SIZE, PROT_READ); + + gem_set_domain(fd, src, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); + for (i = 0; i < len/4; i++) + src_ptr[i] = i; + + do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf)); + gem_close(fd, exec[2].handle); + + gem_set_domain(fd, dst, I915_GEM_DOMAIN_GTT, 0); + for (i = 0; i < len/4; i++) + igt_assert(dst_ptr[i] == i); + + munmap(dst_ptr, len); + munmap(src_ptr, len); +} + +static void test_as_cpu_mmap(int fd, uint32_t src, uint32_t dst, int len) +{ + uint32_t *src_ptr, *dst_ptr; + int i; + BUILD_EXEC; + + src_ptr = gem_mmap__cpu(fd, src, OBJECT_SIZE, PROT_WRITE); + dst_ptr = gem_mmap__cpu(fd, dst, OBJECT_SIZE, PROT_READ); + + gem_set_domain(fd, src, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); + for (i = 0; i < len/4; i++) + src_ptr[i] = i; + + do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf)); + gem_close(fd, exec[2].handle); + + gem_set_domain(fd, dst, I915_GEM_DOMAIN_CPU, 0); + for (i = 0; i < len/4; i++) + igt_assert(dst_ptr[i] == i); + + munmap(dst_ptr, len); + munmap(src_ptr, len); +} + +static double elapsed(const struct timeval *start, + const struct timeval *end, + int loop) +{ + return (1e6*(end->tv_sec - start->tv_sec) + (end->tv_usec - start->tv_usec))/loop; +} + +static const char *bytes_per_sec(char *buf, double v) +{ + const char *order[] = { + "", + "KiB", + "MiB", + "GiB", + "TiB", + NULL, + }, **o = order; + + while (v > 1000 && o[1]) { + v /= 1000; + o++; + } + sprintf(buf, "%.1f%s/s", v, *o); + return buf; +} + +uint32_t *tmp, src, dst; +int fd; + +int main(int argc, char **argv) +{ + int object_size = 0; + uint32_t buf[20]; + int count; + + igt_subtest_init(argc, argv); + igt_skip_on_simulation(); + + if (argc > 1) + object_size = atoi(argv[1]); + if (object_size == 0) + object_size = OBJECT_SIZE; + object_size = (object_size + 3) & -4; + + igt_fixture { + uint32_t devid; + + fd = drm_open_any(); + + dst = gem_create(fd, object_size); + src = gem_create(fd, object_size); + tmp = malloc(object_size); + + gem_set_caching(fd, src, 0); + gem_set_caching(fd, dst, 0); + + devid = intel_get_drm_devid(fd); + is_64bit = intel_gen(devid) >= 8; + exec_flags = HAS_BLT_RING(devid) ? I915_EXEC_BLT : 0; + } + + igt_subtest("uncached-copy-correctness") + test_copy(fd, src, dst, tmp, object_size); + igt_subtest("uncached-copy-performance") { + for (count = 1; count <= 1<<17; count <<= 1) { + struct timeval start, end; + + gettimeofday(&start, NULL); + copy(fd, src, dst, tmp, object_size, count); + gettimeofday(&end, NULL); + igt_info("Time to uncached copy %d bytes x %6d: %7.3fµs, %s\n", + object_size, count, + elapsed(&start, &end, count), + bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6)); + fflush(stdout); + } + } + + igt_subtest("uncached-pwrite-blt-gtt_mmap-correctness") + test_as_gtt_mmap(fd, src, dst, object_size); + igt_subtest("uncached-pwrite-blt-gtt_mmap-performance") { + for (count = 1; count <= 1<<17; count <<= 1) { + struct timeval start, end; + + gettimeofday(&start, NULL); + as_gtt_mmap(fd, src, dst, tmp, object_size, count); + gettimeofday(&end, NULL); + igt_info("** mmap uncached copy %d bytes x %6d: %7.3fµs, %s\n", + object_size, count, + elapsed(&start, &end, count), + bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6)); + fflush(stdout); + } + } + + igt_fixture { + gem_set_caching(fd, src, 1); + gem_set_caching(fd, dst, 1); + } + + igt_subtest("snooped-copy-correctness") + test_copy(fd, src, dst, tmp, object_size); + igt_subtest("snooped-copy-performance") { + for (count = 1; count <= 1<<17; count <<= 1) { + struct timeval start, end; + + gettimeofday(&start, NULL); + copy(fd, src, dst, tmp, object_size, count); + gettimeofday(&end, NULL); + igt_info("Time to snooped copy %d bytes x %6d: %7.3fµs, %s\n", + object_size, count, + elapsed(&start, &end, count), + bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6)); + fflush(stdout); + } + } + + igt_subtest("snooped-pwrite-blt-cpu_mmap-correctness") + test_as_cpu_mmap(fd, src, dst, object_size); + igt_subtest("snooped-pwrite-blt-cpu_mmap-performance") { + for (count = 1; count <= 1<<17; count <<= 1) { + struct timeval start, end; + + gettimeofday(&start, NULL); + as_cpu_mmap(fd, src, dst, tmp, object_size, count); + gettimeofday(&end, NULL); + igt_info("** mmap snooped copy %d bytes x %6d: %7.3fµs, %s\n", + object_size, count, + elapsed(&start, &end, count), + bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6)); + fflush(stdout); + } + } + + igt_fixture { + gem_set_caching(fd, src, 2); + gem_set_caching(fd, dst, 2); + } + + igt_subtest("display-copy-correctness") + test_copy(fd, src, dst, tmp, object_size); + igt_subtest("display-copy-performance") { + for (count = 1; count <= 1<<17; count <<= 1) { + struct timeval start, end; + + gettimeofday(&start, NULL); + copy(fd, src, dst, tmp, object_size, count); + gettimeofday(&end, NULL); + igt_info("Time to display copy %d bytes x %6d: %7.3fµs, %s\n", + object_size, count, + elapsed(&start, &end, count), + bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6)); + fflush(stdout); + } + } + + igt_subtest("display-pwrite-blt-gtt_mmap-correctness") + test_as_gtt_mmap(fd, src, dst, object_size); + igt_subtest("display-pwrite-blt-gtt_mmap-performance") { + for (count = 1; count <= 1<<17; count <<= 1) { + struct timeval start, end; + + gettimeofday(&start, NULL); + as_gtt_mmap(fd, src, dst, tmp, object_size, count); + gettimeofday(&end, NULL); + igt_info("** mmap display copy %d bytes x %6d: %7.3fµs, %s\n", + object_size, count, + elapsed(&start, &end, count), + bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6)); + fflush(stdout); + } + } + + igt_fixture { + free(tmp); + gem_close(fd, src); + gem_close(fd, dst); + + close(fd); + } + + igt_exit(); +} diff --git a/tests/gem_readwrite.c b/tests/gem_readwrite.c index 68c3ff28..a8a7105e 100644 --- a/tests/gem_readwrite.c +++ b/tests/gem_readwrite.c @@ -29,14 +29,13 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/ioctl.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #define OBJECT_SIZE 16384 @@ -44,91 +43,105 @@ static int do_read(int fd, int handle, void *buf, int offset, int size) { - struct drm_i915_gem_pread read; + struct drm_i915_gem_pread gem_pread; /* Ensure that we don't have any convenient data in buf in case * we fail. */ memset(buf, 0xd0, size); - memset(&read, 0, sizeof(read)); - read.handle = handle; - read.data_ptr = (uintptr_t)buf; - read.size = size; - read.offset = offset; + memset(&gem_pread, 0, sizeof(gem_pread)); + gem_pread.handle = handle; + gem_pread.data_ptr = (uintptr_t)buf; + gem_pread.size = size; + gem_pread.offset = offset; - return ioctl(fd, DRM_IOCTL_I915_GEM_PREAD, &read); + return ioctl(fd, DRM_IOCTL_I915_GEM_PREAD, &gem_pread); } static int do_write(int fd, int handle, void *buf, int offset, int size) { - struct drm_i915_gem_pwrite write; + struct drm_i915_gem_pwrite gem_pwrite; - memset(&write, 0, sizeof(write)); - write.handle = handle; - write.data_ptr = (uintptr_t)buf; - write.size = size; - write.offset = offset; + memset(&gem_pwrite, 0, sizeof(gem_pwrite)); + gem_pwrite.handle = handle; + gem_pwrite.data_ptr = (uintptr_t)buf; + gem_pwrite.size = size; + gem_pwrite.offset = offset; - return ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &write); + return ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &gem_pwrite); } -int main(int argc, char **argv) +int fd; +uint32_t handle; + +igt_main { - int fd; uint8_t expected[OBJECT_SIZE]; uint8_t buf[OBJECT_SIZE]; int ret; - int handle; - - fd = drm_open_any(); - - handle = gem_create(fd, OBJECT_SIZE); - - printf("Testing contents of newly created object.\n"); - ret = do_read(fd, handle, buf, 0, OBJECT_SIZE); - assert(ret == 0); - memset(&expected, 0, sizeof(expected)); - assert(memcmp(expected, buf, sizeof(expected)) == 0); - - printf("Testing read beyond end of buffer.\n"); - ret = do_read(fd, handle, buf, OBJECT_SIZE / 2, OBJECT_SIZE); - assert(ret == -1 && errno == EINVAL); - - printf("Testing full write of buffer\n"); - memset(buf, 0, sizeof(buf)); - memset(buf + 1024, 0x01, 1024); - memset(expected + 1024, 0x01, 1024); - ret = do_write(fd, handle, buf, 0, OBJECT_SIZE); - assert(ret == 0); - ret = do_read(fd, handle, buf, 0, OBJECT_SIZE); - assert(ret == 0); - assert(memcmp(buf, expected, sizeof(buf)) == 0); - - printf("Testing partial write of buffer\n"); - memset(buf + 4096, 0x02, 1024); - memset(expected + 4096, 0x02, 1024); - ret = do_write(fd, handle, buf + 4096, 4096, 1024); - assert(ret == 0); - ret = do_read(fd, handle, buf, 0, OBJECT_SIZE); - assert(ret == 0); - assert(memcmp(buf, expected, sizeof(buf)) == 0); - - printf("Testing partial read of buffer\n"); - ret = do_read(fd, handle, buf, 512, 1024); - assert(ret == 0); - assert(memcmp(buf, expected + 512, 1024) == 0); - - printf("Testing read of bad buffer handle\n"); - ret = do_read(fd, 1234, buf, 0, 1024); - assert(ret == -1 && errno == ENOENT); - - printf("Testing write of bad buffer handle\n"); - ret = do_write(fd, 1234, buf, 0, 1024); - assert(ret == -1 && errno == ENOENT); - - close(fd); - - return 0; + + igt_skip_on_simulation(); + + igt_fixture { + fd = drm_open_any(); + + handle = gem_create(fd, OBJECT_SIZE); + } + + igt_subtest("new-obj") { + igt_info("Testing contents of newly created object.\n"); + ret = do_read(fd, handle, buf, 0, OBJECT_SIZE); + igt_assert(ret == 0); + memset(&expected, 0, sizeof(expected)); + igt_assert(memcmp(expected, buf, sizeof(expected)) == 0); + } + + igt_subtest("beyond-EOB") { + igt_info("Testing read beyond end of buffer.\n"); + ret = do_read(fd, handle, buf, OBJECT_SIZE / 2, OBJECT_SIZE); + igt_assert(ret == -1 && errno == EINVAL); + } + + igt_subtest("read-write") { + igt_info("Testing full write of buffer\n"); + memset(buf, 0, sizeof(buf)); + memset(buf + 1024, 0x01, 1024); + memset(expected + 1024, 0x01, 1024); + ret = do_write(fd, handle, buf, 0, OBJECT_SIZE); + igt_assert(ret == 0); + ret = do_read(fd, handle, buf, 0, OBJECT_SIZE); + igt_assert(ret == 0); + igt_assert(memcmp(buf, expected, sizeof(buf)) == 0); + + igt_info("Testing partial write of buffer\n"); + memset(buf + 4096, 0x02, 1024); + memset(expected + 4096, 0x02, 1024); + ret = do_write(fd, handle, buf + 4096, 4096, 1024); + igt_assert(ret == 0); + ret = do_read(fd, handle, buf, 0, OBJECT_SIZE); + igt_assert(ret == 0); + igt_assert(memcmp(buf, expected, sizeof(buf)) == 0); + + igt_info("Testing partial read of buffer\n"); + ret = do_read(fd, handle, buf, 512, 1024); + igt_assert(ret == 0); + igt_assert(memcmp(buf, expected + 512, 1024) == 0); + } + + igt_subtest("read-bad-handle") { + igt_info("Testing read of bad buffer handle\n"); + ret = do_read(fd, 1234, buf, 0, 1024); + igt_assert(ret == -1 && errno == ENOENT); + } + + igt_subtest("write-bad-handle") { + igt_info("Testing write of bad buffer handle\n"); + ret = do_write(fd, 1234, buf, 0, 1024); + igt_assert(ret == -1 && errno == ENOENT); + } + + igt_fixture + close(fd); } diff --git a/tests/gem_reg_read.c b/tests/gem_reg_read.c index 1d6db1f1..4220d69f 100644 --- a/tests/gem_reg_read.c +++ b/tests/gem_reg_read.c @@ -27,7 +27,9 @@ #include <stdio.h> #include <string.h> -#include "i915_drm.h" +#include <errno.h> + +#include "ioctl_wrappers.h" #include "drmtest.h" struct local_drm_i915_reg_read { @@ -37,62 +39,41 @@ struct local_drm_i915_reg_read { #define REG_READ_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x31, struct local_drm_i915_reg_read) -static void handle_bad(int ret, int lerrno, int expected, const char *desc) -{ - if (ret != 0 && lerrno != expected) { - fprintf(stderr, "%s - errno was %d, but should have been %d\n", - desc, lerrno, expected); - exit(EXIT_FAILURE); - } else if (ret == 0) { - fprintf(stderr, "%s - Command succeeded, but should have failed\n", - desc); - exit(EXIT_FAILURE); - } -} - static uint64_t timer_query(int fd) { - struct local_drm_i915_reg_read read; - int ret; + struct local_drm_i915_reg_read reg_read; - read.offset = 0x2358; - ret = drmIoctl(fd, REG_READ_IOCTL, &read); - if (ret) { + reg_read.offset = 0x2358; + if (drmIoctl(fd, REG_READ_IOCTL, ®_read)) { perror("positive test case failed: "); - exit(EXIT_FAILURE); + igt_fail(1); } - return read.val; + return reg_read.val; } -int main(int argc, char *argv[]) +igt_simple_main { - struct local_drm_i915_reg_read read; - int ret, fd; - uint64_t val; + struct local_drm_i915_reg_read reg_read; + int fd, ret; fd = drm_open_any(); - read.offset = 0x2358; - ret = drmIoctl(fd, REG_READ_IOCTL, &read); - if (errno == EINVAL) - exit(77); - else if (ret) - exit(EXIT_FAILURE); + reg_read.offset = 0x2358; + ret = drmIoctl(fd, REG_READ_IOCTL, ®_read); + igt_assert(ret == 0 || errno == EINVAL); + igt_require(ret == 0); - val = timer_query(fd); + reg_read.val = timer_query(fd); sleep(1); - if (timer_query(fd) == val) { - fprintf(stderr, "Timer isn't moving, probably busted\n"); - exit(EXIT_FAILURE); - } + /* Check that timer is moving and isn't busted. */ + igt_assert(timer_query(fd) != reg_read.val); /* bad reg */ - read.offset = 0x12345678; - ret = drmIoctl(fd, REG_READ_IOCTL, &read); - handle_bad(ret, errno, EINVAL, "bad register"); + reg_read.offset = 0x12345678; + ret = drmIoctl(fd, REG_READ_IOCTL, ®_read); - close(fd); + igt_assert(ret != 0 && errno == EINVAL); - exit(EXIT_SUCCESS); + close(fd); } diff --git a/tests/gem_reloc_overflow.c b/tests/gem_reloc_overflow.c new file mode 100644 index 00000000..06a315fd --- /dev/null +++ b/tests/gem_reloc_overflow.c @@ -0,0 +1,381 @@ +/* + * Copyright © 2013 Google + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Kees Cook <keescook@chromium.org> + * Daniel Vetter <daniel.vetter@ffwll.ch> + * Rafael Barbalho <rafael.barbalho@intel.com> + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <unistd.h> +#include <malloc.h> +#include <limits.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/types.h> +#include "drm.h" +#include "ioctl_wrappers.h" +#include "intel_chipset.h" +#include "drmtest.h" +#include "intel_io.h" + +/* + * Testcase: Kernel relocation overflows are caught. + */ + +int fd, entries, num; +size_t reloc_size; +uint32_t *handles; +struct drm_i915_gem_exec_object2 *execobjs; +struct drm_i915_gem_execbuffer2 execbuf = { 0 }; +struct drm_i915_gem_relocation_entry *reloc; + +uint32_t handle; +uint32_t batch_handle; + +static void source_offset_tests(int devid, bool reloc_gtt) +{ + struct drm_i915_gem_relocation_entry single_reloc; + void *dst_gtt; + const char *relocation_type; + + if (reloc_gtt) + relocation_type = "reloc-gtt"; + else + relocation_type = "reloc-cpu"; + + igt_fixture { + handle = gem_create(fd, 8192); + + execobjs[1].handle = batch_handle; + execobjs[1].relocation_count = 0; + execobjs[1].relocs_ptr = 0; + + execobjs[0].handle = handle; + execobjs[0].relocation_count = 1; + execobjs[0].relocs_ptr = (uintptr_t) &single_reloc; + execbuf.buffer_count = 2; + + if (reloc_gtt) { + dst_gtt = gem_mmap(fd, handle, 8192, PROT_READ | PROT_WRITE); + igt_assert(dst_gtt != MAP_FAILED); + gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); + memset(dst_gtt, 0, 8192); + munmap(dst_gtt, 8192); + relocation_type = "reloc-gtt"; + } else { + relocation_type = "reloc-cpu"; + } + } + + /* Special tests for 64b relocs. */ + igt_subtest_f("source-offset-page-stradle-gen8-%s", relocation_type) { + igt_require(intel_gen(devid) >= 8); + single_reloc.offset = 4096 - 4; + single_reloc.delta = 0; + single_reloc.target_handle = handle; + single_reloc.read_domains = I915_GEM_DOMAIN_RENDER; + single_reloc.write_domain = I915_GEM_DOMAIN_RENDER; + single_reloc.presumed_offset = 0; + + igt_assert(ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf) == 0); + single_reloc.delta = 1024; + igt_assert(ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf) == 0); + } + + igt_subtest_f("source-offset-end-gen8-%s", relocation_type) { + igt_require(intel_gen(devid) >= 8); + single_reloc.offset = 8192 - 8; + single_reloc.delta = 0; + single_reloc.target_handle = handle; + single_reloc.read_domains = I915_GEM_DOMAIN_RENDER; + single_reloc.write_domain = I915_GEM_DOMAIN_RENDER; + single_reloc.presumed_offset = 0; + + igt_assert(ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf) == 0); + } + + igt_subtest_f("source-offset-overflow-gen8-%s", relocation_type) { + igt_require(intel_gen(devid) >= 8); + single_reloc.offset = 8192 - 4; + single_reloc.delta = 0; + single_reloc.target_handle = handle; + single_reloc.read_domains = I915_GEM_DOMAIN_RENDER; + single_reloc.write_domain = I915_GEM_DOMAIN_RENDER; + single_reloc.presumed_offset = 0; + + igt_assert(ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf) != 0); + igt_assert(errno == EINVAL); + } + + /* Tests for old 4byte relocs on pre-gen8. */ + igt_subtest_f("source-offset-end-%s", relocation_type) { + igt_require(intel_gen(devid) < 8); + single_reloc.offset = 8192 - 4; + single_reloc.delta = 0; + single_reloc.target_handle = handle; + single_reloc.read_domains = I915_GEM_DOMAIN_RENDER; + single_reloc.write_domain = I915_GEM_DOMAIN_RENDER; + single_reloc.presumed_offset = 0; + + igt_assert(ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf) == 0); + } + + igt_subtest_f("source-offset-big-%s", relocation_type) { + single_reloc.offset = 8192; + single_reloc.delta = 0; + single_reloc.target_handle = handle; + single_reloc.read_domains = I915_GEM_DOMAIN_RENDER; + single_reloc.write_domain = I915_GEM_DOMAIN_RENDER; + single_reloc.presumed_offset = 0; + + igt_assert(ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf) != 0); + igt_assert(errno == EINVAL); + } + + igt_subtest_f("source-offset-negative-%s", relocation_type) { + single_reloc.offset = (int64_t) -4; + single_reloc.delta = 0; + single_reloc.target_handle = handle; + single_reloc.read_domains = I915_GEM_DOMAIN_RENDER; + single_reloc.write_domain = I915_GEM_DOMAIN_RENDER; + single_reloc.presumed_offset = 0; + + igt_assert(ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf) != 0); + igt_assert(errno == EINVAL); + } + + igt_subtest_f("source-offset-unaligned-%s", relocation_type) { + single_reloc.offset = 1; + single_reloc.delta = 0; + single_reloc.target_handle = handle; + single_reloc.read_domains = I915_GEM_DOMAIN_RENDER; + single_reloc.write_domain = I915_GEM_DOMAIN_RENDER; + single_reloc.presumed_offset = 0; + + igt_assert(ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf) != 0); + igt_assert(errno == EINVAL); + } + + igt_fixture { + gem_close(fd, handle); + } +} + +static void reloc_tests(void) +{ + int i; + unsigned int total_unsigned = 0; + + igt_subtest("invalid-address") { + /* Attempt unmapped single entry. */ + execobjs[0].relocation_count = 1; + execobjs[0].relocs_ptr = 0; + execbuf.buffer_count = 1; + + errno = 0; + ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + igt_assert(errno == EFAULT); + } + + igt_subtest("single-overflow") { + /* Attempt single overflowed entry. */ + execobjs[0].relocation_count = (1 << 31); + execobjs[0].relocs_ptr = (uintptr_t)reloc; + execbuf.buffer_count = 1; + + errno = 0; + ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + igt_assert(errno == EINVAL); + } + + igt_fixture { + execobjs[0].handle = batch_handle; + execobjs[0].relocation_count = 0; + execobjs[0].relocs_ptr = 0; + + execbuf.buffer_count = 1; + + /* Make sure the batch would succeed except for the thing we're + * testing. */ + execbuf.batch_start_offset = 0; + execbuf.batch_len = 8; + igt_assert(ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf) == 0); + } + + igt_subtest("batch-start-unaligned") { + execbuf.batch_start_offset = 1; + execbuf.batch_len = 8; + + igt_assert(ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf) != 0); + igt_assert(errno == EINVAL); + } + + igt_subtest("batch-end-unaligned") { + execbuf.batch_start_offset = 0; + execbuf.batch_len = 7; + + igt_assert(ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf) != 0); + igt_assert(errno == EINVAL); + } + + igt_fixture { + /* Undo damage for next tests. */ + execbuf.batch_start_offset = 0; + execbuf.batch_len = 8; + } + + igt_subtest("wrapped-overflow") { + /* Attempt wrapped overflow entries. */ + for (i = 0; i < num; i++) { + struct drm_i915_gem_exec_object2 *obj = &execobjs[i]; + obj->handle = handles[i]; + + if (i == num - 1) { + /* Wraps to 1 on last count. */ + obj->relocation_count = 1 - total_unsigned; + obj->relocs_ptr = (uintptr_t)reloc; + } else { + obj->relocation_count = entries; + obj->relocs_ptr = (uintptr_t)reloc; + } + + total_unsigned += obj->relocation_count; + } + execbuf.buffer_count = num; + + errno = 0; + ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + igt_assert(errno == EINVAL); + } +} + +static void buffer_count_tests(void) +{ + igt_subtest("buffercount-overflow") { + for (int i = 0; i < num; i++) { + execobjs[i].relocation_count = 0; + execobjs[i].relocs_ptr = 0; + execobjs[i].handle = handles[i]; + } + + execobjs[0].relocation_count = 0; + execobjs[0].relocs_ptr = 0; + /* We only have num buffers actually, but the overflow will make + * sure we blow up the kernel before we blow up userspace. */ + execbuf.buffer_count = num; + + /* Put a real batch at the end. */ + execobjs[num - 1].handle = batch_handle; + + /* Make sure the basic thing would work first ... */ + errno = 0; + ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + igt_assert(errno == 0); + + /* ... then be evil: Overflow of the pointer table (which has a + * bit of lead datastructures, so no + 1 needed to overflow). */ + execbuf.buffer_count = INT_MAX / sizeof(void *); + + errno = 0; + ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + igt_assert(errno == EINVAL); + + /* ... then be evil: Copying/allocating the array. */ + execbuf.buffer_count = UINT_MAX / sizeof(execobjs[0]) + 1; + + errno = 0; + ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + igt_assert(errno == EINVAL); + } +} + +igt_main +{ + int devid = 0; + + igt_fixture { + int ring; + uint32_t batch_data [2] = { MI_NOOP, MI_BATCH_BUFFER_END }; + + fd = drm_open_any(); + + devid = intel_get_drm_devid(fd); + + /* Create giant reloc buffer area. */ + num = 257; + entries = ((1ULL << 32) / (num - 1)); + reloc_size = entries * sizeof(struct drm_i915_gem_relocation_entry); + reloc = mmap(NULL, reloc_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + igt_assert(reloc != MAP_FAILED); + + /* Allocate the handles we'll need to wrap. */ + handles = calloc(num, sizeof(*handles)); + for (int i = 0; i < num; i++) + handles[i] = gem_create(fd, 4096); + + if (intel_gen(devid) >= 6) + ring = I915_EXEC_BLT; + else + ring = 0; + + /* Create relocation objects. */ + execobjs = calloc(num, sizeof(*execobjs)); + execbuf.buffers_ptr = (uintptr_t)execobjs; + execbuf.batch_start_offset = 0; + execbuf.batch_len = 8; + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = ring; + i915_execbuffer2_set_context_id(execbuf, 0); + execbuf.rsvd2 = 0; + + batch_handle = gem_create(fd, 4096); + + gem_write(fd, batch_handle, 0, batch_data, sizeof(batch_data)); + } + + reloc_tests(); + + source_offset_tests(devid, false); + source_offset_tests(devid, true); + + buffer_count_tests(); + + igt_fixture { + gem_close(fd, batch_handle); + close(fd); + } +} diff --git a/tests/gem_reloc_vs_gpu.c b/tests/gem_reloc_vs_gpu.c index 47681d51..271f4f67 100644 --- a/tests/gem_reloc_vs_gpu.c +++ b/tests/gem_reloc_vs_gpu.c @@ -1,5 +1,5 @@ /* - * Copyright © 2011 Intel Corporation + * Copyright © 2011,2013 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,21 +25,26 @@ * */ +#define _GNU_SOURCE #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> -#include "drm.h" -#include "i915_drm.h" +#include <signal.h> +#include <sys/wait.h> + +#include <drm.h> + +#include "ioctl_wrappers.h" #include "drmtest.h" -#include "intel_bufmgr.h" -#include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_chipset.h" +#include "intel_io.h" +#include "igt_debugfs.h" +#include "igt_aux.h" /* * Testcase: Kernel relocations vs. gpu races @@ -58,17 +63,6 @@ uint32_t devid; int special_reloc_ofs; int special_batch_len; -#define GFX_OP_PIPE_CONTROL ((0x3<<29)|(0x3<<27)|(0x2<<24)|2) -#define PIPE_CONTROL_WRITE_IMMEDIATE (1<<14) -#define PIPE_CONTROL_WRITE_TIMESTAMP (3<<14) -#define PIPE_CONTROL_DEPTH_STALL (1<<13) -#define PIPE_CONTROL_WC_FLUSH (1<<12) -#define PIPE_CONTROL_IS_FLUSH (1<<11) /* MBZ on Ironlake */ -#define PIPE_CONTROL_TC_FLUSH (1<<10) /* GM45+ only */ -#define PIPE_CONTROL_STALL_AT_SCOREBOARD (1<<1) -#define PIPE_CONTROL_CS_STALL (1<<20) -#define PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */ - static void create_special_bo(void) { uint32_t data[1024]; @@ -79,12 +73,22 @@ static void create_special_bo(void) memset(data, 0, 4096); special_bo = drm_intel_bo_alloc(bufmgr, "special batch", 4096, 4096); - BATCH(XY_COLOR_BLT_CMD | COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB); + if (intel_gen(devid) >= 8) { + BATCH(MI_NOOP); + BATCH(XY_COLOR_BLT_CMD_NOLEN | 5 | + COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB); + } else { + BATCH(XY_COLOR_BLT_CMD_NOLEN | 4 | + COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB); + } + BATCH((3 << 24) | (0xf0 << 16) | small_pitch); BATCH(0); BATCH(1 << 16 | 1); special_reloc_ofs = 4*len; BATCH(0); + if (intel_gen(devid) >= 8) + BATCH(0); BATCH(0xdeadbeef); #define CMD_POLY_STIPPLE_OFFSET 0x7906 @@ -93,7 +97,7 @@ static void create_special_bo(void) BATCH(CMD_POLY_STIPPLE_OFFSET << 16); BATCH(0); } - assert(len % 2 == 0); + igt_assert(len % 2 == 0); BATCH(MI_NOOP); BATCH(MI_BATCH_BUFFER_END); @@ -113,23 +117,21 @@ static void emit_dummy_load(int pitch) } for (i = 0; i < 10; i++) { - BEGIN_BATCH(8); - OUT_BATCH(XY_SRC_COPY_BLT_CMD | - XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB | - tile_flags); + BLIT_COPY_BATCH_START(devid, tile_flags); OUT_BATCH((3 << 24) | /* 32 bits */ (0xcc << 16) | /* copy ROP */ pitch); OUT_BATCH(0 << 16 | 1024); OUT_BATCH((2048) << 16 | (2048)); OUT_RELOC_FENCED(dummy_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(devid); OUT_BATCH(0 << 16 | 0); OUT_BATCH(pitch); OUT_RELOC_FENCED(dummy_bo, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(devid); ADVANCE_BATCH(); - if (IS_GEN6(devid) || IS_GEN7(devid)) { + if (intel_gen(devid) >= 6) { BEGIN_BATCH(3); OUT_BATCH(XY_SETUP_CLIP_BLT_CMD); OUT_BATCH(0); @@ -140,23 +142,97 @@ static void emit_dummy_load(int pitch) intel_batchbuffer_flush(batch); } -#define MAX_BLT_SIZE 128 -int main(int argc, char **argv) +static void faulting_reloc_and_emit(int fd, drm_intel_bo *target_bo) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 exec[2]; + struct drm_i915_gem_relocation_entry reloc[1]; + uint32_t handle_relocs; + void *gtt_relocs; + int ring; + + if (intel_gen(devid) >= 6) + ring = I915_EXEC_BLT; + else + ring = 0; + + exec[0].handle = target_bo->handle; + exec[0].relocation_count = 0; + exec[0].relocs_ptr = 0; + exec[0].alignment = 0; + exec[0].offset = 0; + exec[0].flags = 0; + exec[0].rsvd1 = 0; + exec[0].rsvd2 = 0; + + reloc[0].offset = special_reloc_ofs; + reloc[0].delta = 0; + reloc[0].target_handle = target_bo->handle; + reloc[0].read_domains = I915_GEM_DOMAIN_RENDER; + reloc[0].write_domain = I915_GEM_DOMAIN_RENDER; + reloc[0].presumed_offset = 0; + + handle_relocs = gem_create(fd, 4096); + gem_write(fd, handle_relocs, 0, reloc, sizeof(reloc)); + gtt_relocs = gem_mmap(fd, handle_relocs, 4096, + PROT_READ | PROT_WRITE); + igt_assert(gtt_relocs); + + exec[1].handle = special_bo->handle; + exec[1].relocation_count = 1; + /* A newly mmap gtt bo will fault on first access. */ + exec[1].relocs_ptr = (uintptr_t)gtt_relocs; + exec[1].alignment = 0; + exec[1].offset = 0; + exec[1].flags = 0; + exec[1].rsvd1 = 0; + exec[1].rsvd2 = 0; + + execbuf.buffers_ptr = (uintptr_t)exec; + execbuf.buffer_count = 2; + execbuf.batch_start_offset = 0; + execbuf.batch_len = special_batch_len; + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = ring; + i915_execbuffer2_set_context_id(execbuf, 0); + execbuf.rsvd2 = 0; + + gem_execbuf(fd, &execbuf); + + gem_close(fd, handle_relocs); +} + +static void reloc_and_emit(int fd, drm_intel_bo *target_bo) +{ + int ring; + + if (intel_gen(devid) >= 6) + ring = I915_EXEC_BLT; + else + ring = 0; + + drm_intel_bo_emit_reloc(special_bo, special_reloc_ofs, + target_bo, + 0, + I915_GEM_DOMAIN_RENDER, + I915_GEM_DOMAIN_RENDER); + drm_intel_bo_mrb_exec(special_bo, special_batch_len, NULL, + 0, 0, ring); + +} + +static void do_test(int fd, bool faulting_reloc) { uint32_t tiling_mode = I915_TILING_X; unsigned long pitch, act_size; - int fd, i, ring; uint32_t test; + int i; - memset(blob, 'A', sizeof(blob)); - - fd = drm_open_any(); - - bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - /* disable reuse, otherwise the test fails */ - //drm_intel_bufmgr_gem_enable_reuse(bufmgr); - devid = intel_get_drm_devid(fd); - batch = intel_batchbuffer_alloc(bufmgr, devid); + if (faulting_reloc) + igt_disable_prefault(); act_size = 2048; dummy_bo = drm_intel_bo_alloc_tiled(bufmgr, "tiled dummy_bo", act_size, act_size, @@ -166,41 +242,125 @@ int main(int argc, char **argv) create_special_bo(); - if (intel_gen(devid) >= 6) - ring = I915_EXEC_BLT; - else - ring = 0; - for (i = 0; i < NUM_TARGET_BOS; i++) { pc_target_bo[i] = drm_intel_bo_alloc(bufmgr, "special batch", 4096, 4096); emit_dummy_load(pitch); - assert(pc_target_bo[i]->offset == 0); - drm_intel_bo_emit_reloc(special_bo, special_reloc_ofs, - pc_target_bo[i], - 0, - I915_GEM_DOMAIN_RENDER, - I915_GEM_DOMAIN_RENDER); - drm_intel_bo_mrb_exec(special_bo, special_batch_len, NULL, - 0, 0, ring); + igt_assert(pc_target_bo[i]->offset == 0); + + if (faulting_reloc) + faulting_reloc_and_emit(fd, pc_target_bo[i]); + else + reloc_and_emit(fd, pc_target_bo[i]); } /* Only check at the end to avoid unnecessary synchronous behaviour. */ for (i = 0; i < NUM_TARGET_BOS; i++) { drm_intel_bo_get_subdata(pc_target_bo[i], 0, 4, &test); - if (test != 0xdeadbeef) { - fprintf(stderr, "mismatch in buffer %i: 0x%08x instead of 0xdeadbeef\n", i, test); - exit(1); - } + igt_assert_f(test == 0xdeadbeef, + "mismatch in buffer %i: 0x%08x instead of 0xdeadbeef\n", i, test); drm_intel_bo_unreference(pc_target_bo[i]); } drm_intel_gem_bo_map_gtt(dummy_bo); drm_intel_gem_bo_unmap_gtt(dummy_bo); - intel_batchbuffer_free(batch); - drm_intel_bufmgr_destroy(bufmgr); + drm_intel_bo_unreference(special_bo); + drm_intel_bo_unreference(dummy_bo); + + if (faulting_reloc) + igt_enable_prefault(); +} + +#define INTERRUPT (1 << 0) +#define FAULTING (1 << 1) +#define THRASH (1 << 2) +#define THRASH_INACTIVE (1 << 3) +#define ALL_FLAGS (INTERRUPT | FAULTING | THRASH | THRASH_INACTIVE) +static void do_forked_test(int fd, unsigned flags) +{ + int num_threads = sysconf(_SC_NPROCESSORS_ONLN); + struct igt_helper_process thrasher = {}; + + if (flags & (THRASH | THRASH_INACTIVE)) { + uint64_t val = (flags & THRASH_INACTIVE) ? + (DROP_RETIRE | DROP_BOUND | DROP_UNBOUND) : DROP_ALL; - close(fd); + igt_fork_helper(&thrasher) { + while (1) { + usleep(1000); + igt_drop_caches_set(val); + } + } + } + + igt_fork(i, num_threads * 4) { + /* re-create process local data */ + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + batch = intel_batchbuffer_alloc(bufmgr, devid); + + if (flags & INTERRUPT) + igt_fork_signal_helper(); + + do_test(fd, flags & FAULTING); + + if (flags & INTERRUPT) + igt_stop_signal_helper(); + } + + igt_waitchildren(); + if (flags & (THRASH | THRASH_INACTIVE)) + igt_stop_helper(&thrasher); +} - return 0; +int fd; + +#define MAX_BLT_SIZE 128 +igt_main +{ + igt_skip_on_simulation(); + + memset(blob, 'A', sizeof(blob)); + + igt_fixture { + fd = drm_open_any(); + + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + /* disable reuse, otherwise the test fails */ + //drm_intel_bufmgr_gem_enable_reuse(bufmgr); + devid = intel_get_drm_devid(fd); + batch = intel_batchbuffer_alloc(bufmgr, devid); + } + + igt_subtest("normal") + do_test(fd, false); + + igt_subtest("faulting-reloc") + do_test(fd, true); + + igt_fork_signal_helper(); + igt_subtest("interruptible") + do_test(fd, false); + + igt_subtest("faulting-reloc-interruptible") + do_test(fd, true); + igt_stop_signal_helper(); + + for (unsigned flags = 0; flags <= ALL_FLAGS; flags++) { + if ((flags & THRASH) && (flags & THRASH_INACTIVE)) + continue; + + igt_subtest_f("forked%s%s%s%s", + flags & INTERRUPT ? "-interruptible" : "", + flags & FAULTING ? "-faulting-reloc" : "", + flags & THRASH ? "-thrashing" : "", + flags & THRASH_INACTIVE ? "-thrash-inactive" : "") + do_forked_test(fd, flags); + } + + igt_fixture { + intel_batchbuffer_free(batch); + drm_intel_bufmgr_destroy(bufmgr); + + close(fd); + } } diff --git a/tests/gem_render_copy.c b/tests/gem_render_copy.c new file mode 100644 index 00000000..fd26b43f --- /dev/null +++ b/tests/gem_render_copy.c @@ -0,0 +1,193 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Damien Lespiau <damien.lespiau@intel.com> + */ + +/* + * This file is a basic test for the render_copy() function, a very simple + * workload for the 3D engine. + */ + +#include <stdbool.h> +#include <unistd.h> +#include <cairo.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <getopt.h> + +#include <drm.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_io.h" +#include "intel_chipset.h" +#include "igt_aux.h" + +#define WIDTH 512 +#define STRIDE (WIDTH*4) +#define HEIGHT 512 +#define SIZE (HEIGHT*STRIDE) + +#define SRC_COLOR 0xffff00ff +#define DST_COLOR 0xfff0ff00 + +typedef struct { + int drm_fd; + uint32_t devid; + drm_intel_bufmgr *bufmgr; + uint32_t linear[WIDTH * HEIGHT]; +} data_t; + +static void scratch_buf_write_to_png(struct igt_buf *buf, const char *filename) +{ + cairo_surface_t *surface; + cairo_status_t ret; + + drm_intel_bo_map(buf->bo, 0); + surface = cairo_image_surface_create_for_data(buf->bo->virtual, + CAIRO_FORMAT_RGB24, + igt_buf_width(buf), + igt_buf_height(buf), + buf->stride); + ret = cairo_surface_write_to_png(surface, filename); + igt_assert(ret == CAIRO_STATUS_SUCCESS); + cairo_surface_destroy(surface); + drm_intel_bo_unmap(buf->bo); +} + +static void scratch_buf_init(data_t *data, struct igt_buf *buf, + int width, int height, int stride, uint32_t color) +{ + drm_intel_bo *bo; + int i; + + bo = drm_intel_bo_alloc(data->bufmgr, "", SIZE, 4096); + for (i = 0; i < width * height; i++) + data->linear[i] = color; + gem_write(data->drm_fd, bo->handle, 0, data->linear, + sizeof(data->linear)); + + buf->bo = bo; + buf->stride = stride; + buf->tiling = I915_TILING_NONE; + buf->size = SIZE; +} + +static void +scratch_buf_check(data_t *data, struct igt_buf *buf, int x, int y, + uint32_t color) +{ + uint32_t val; + + gem_read(data->drm_fd, buf->bo->handle, 0, + data->linear, sizeof(data->linear)); + val = data->linear[y * WIDTH + x]; + igt_assert_f(val == color, + "Expected 0x%08x, found 0x%08x at (%d,%d)\n", + color, val, x, y); +} + +int main(int argc, char **argv) +{ + data_t data = {0, }; + struct intel_batchbuffer *batch = NULL; + struct igt_buf src, dst; + igt_render_copyfunc_t render_copy = NULL; + int opt; + int opt_dump_png = false; + int opt_dump_aub = igt_aub_dump_enabled(); + + igt_simple_init(); + + while ((opt = getopt(argc, argv, "d")) != -1) { + switch (opt) { + case 'd': + opt_dump_png = true; + break; + default: + break; + } + } + + igt_fixture { + data.drm_fd = drm_open_any_render(); + data.devid = intel_get_drm_devid(data.drm_fd); + + data.bufmgr = drm_intel_bufmgr_gem_init(data.drm_fd, 4096); + igt_assert(data.bufmgr); + + render_copy = igt_get_render_copyfunc(data.devid); + igt_require_f(render_copy, + "no render-copy function\n"); + + batch = intel_batchbuffer_alloc(data.bufmgr, data.devid); + igt_assert(batch); + } + + scratch_buf_init(&data, &src, WIDTH, HEIGHT, STRIDE, SRC_COLOR); + scratch_buf_init(&data, &dst, WIDTH, HEIGHT, STRIDE, DST_COLOR); + + scratch_buf_check(&data, &src, WIDTH / 2, HEIGHT / 2, SRC_COLOR); + scratch_buf_check(&data, &dst, WIDTH / 2, HEIGHT / 2, DST_COLOR); + + if (opt_dump_png) { + scratch_buf_write_to_png(&src, "source.png"); + scratch_buf_write_to_png(&dst, "destination.png"); + } + + if (opt_dump_aub) { + drm_intel_bufmgr_gem_set_aub_filename(data.bufmgr, + "rendercopy.aub"); + drm_intel_bufmgr_gem_set_aub_dump(data.bufmgr, true); + } + + render_copy(batch, NULL, + &src, 0, 0, WIDTH, HEIGHT, + &dst, WIDTH / 2, HEIGHT / 2); + + if (opt_dump_png) + scratch_buf_write_to_png(&dst, "result.png"); + + if (opt_dump_aub) { + drm_intel_gem_bo_aub_dump_bmp(dst.bo, + 0, 0, WIDTH, HEIGHT, + AUB_DUMP_BMP_FORMAT_ARGB_8888, + STRIDE, 0); + drm_intel_bufmgr_gem_set_aub_dump(data.bufmgr, false); + } else { + scratch_buf_check(&data, &dst, 10, 10, DST_COLOR); + scratch_buf_check(&data, &dst, WIDTH - 10, HEIGHT - 10, SRC_COLOR); + } + + return 0; +} diff --git a/tests/gem_render_copy_redux.c b/tests/gem_render_copy_redux.c new file mode 100644 index 00000000..73dcb722 --- /dev/null +++ b/tests/gem_render_copy_redux.c @@ -0,0 +1,247 @@ +/* + * Copyright © 2013-2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Damien Lespiau <damien.lespiau@intel.com> + */ + +/* + * This file is an "advanced" test for the render_copy() function, a very simple + * workload for the 3D engine. The basic test in gem_render_copy.c is intentionally + * kept extremely simple to allow for aub instrumentation and to ease debugging of + * the render copy functions themselves. This test on the overhand aims to stress + * the execbuffer interface with a simple render workload. + */ + +#include <stdbool.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <getopt.h> + +#include <drm.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_io.h" +#include "intel_chipset.h" +#include "igt_aux.h" + +#define WIDTH 512 +#define STRIDE (WIDTH*4) +#define HEIGHT 512 +#define SIZE (HEIGHT*STRIDE) + +#define SRC_COLOR 0xffff00ff +#define DST_COLOR 0xfff0ff00 + +typedef struct { + int fd; + uint32_t devid; + drm_intel_bufmgr *bufmgr; + struct intel_batchbuffer *batch; + igt_render_copyfunc_t render_copy; + uint32_t linear[WIDTH * HEIGHT]; +} data_t; + +static void data_init(data_t *data) +{ + data->fd = drm_open_any_render(); + data->devid = intel_get_drm_devid(data->fd); + + data->bufmgr = drm_intel_bufmgr_gem_init(data->fd, 4096); + igt_assert(data->bufmgr); + + data->render_copy = igt_get_render_copyfunc(data->devid); + igt_require_f(data->render_copy, + "no render-copy function\n"); + + data->batch = intel_batchbuffer_alloc(data->bufmgr, data->devid); + igt_assert(data->batch); +} + +static void data_fini(data_t *data) +{ + intel_batchbuffer_free(data->batch); + drm_intel_bufmgr_destroy(data->bufmgr); + close(data->fd); +} + +static void scratch_buf_init(data_t *data, struct igt_buf *buf, + int width, int height, int stride, uint32_t color) +{ + drm_intel_bo *bo; + int i; + + bo = drm_intel_bo_alloc(data->bufmgr, "", SIZE, 4096); + for (i = 0; i < width * height; i++) + data->linear[i] = color; + gem_write(data->fd, bo->handle, 0, data->linear, + sizeof(data->linear)); + + buf->bo = bo; + buf->stride = stride; + buf->tiling = I915_TILING_NONE; + buf->size = SIZE; +} + +static void scratch_buf_fini(data_t *data, struct igt_buf *buf) +{ + dri_bo_unreference(buf->bo); + memset(buf, 0, sizeof(*buf)); +} + +static void +scratch_buf_check(data_t *data, struct igt_buf *buf, int x, int y, + uint32_t color) +{ + uint32_t val; + + gem_read(data->fd, buf->bo->handle, 0, + data->linear, sizeof(data->linear)); + val = data->linear[y * WIDTH + x]; + igt_assert_f(val == color, + "Expected 0x%08x, found 0x%08x at (%d,%d)\n", + color, val, x, y); +} + +static void copy(data_t *data) +{ + struct igt_buf src, dst; + + scratch_buf_init(data, &src, WIDTH, HEIGHT, STRIDE, SRC_COLOR); + scratch_buf_init(data, &dst, WIDTH, HEIGHT, STRIDE, DST_COLOR); + + scratch_buf_check(data, &src, WIDTH / 2, HEIGHT / 2, SRC_COLOR); + scratch_buf_check(data, &dst, WIDTH / 2, HEIGHT / 2, DST_COLOR); + + data->render_copy(data->batch, NULL, + &src, 0, 0, WIDTH, HEIGHT, + &dst, WIDTH / 2, HEIGHT / 2); + + scratch_buf_check(data, &dst, 10, 10, DST_COLOR); + scratch_buf_check(data, &dst, WIDTH - 10, HEIGHT - 10, SRC_COLOR); + + scratch_buf_fini(data, &src); + scratch_buf_fini(data, &dst); +} + +static void copy_flink(data_t *data) +{ + data_t local; + struct igt_buf src, dst; + struct igt_buf local_src, local_dst; + struct igt_buf flink; + uint32_t name; + + data_init(&local); + + scratch_buf_init(data, &src, WIDTH, HEIGHT, STRIDE, 0); + scratch_buf_init(data, &dst, WIDTH, HEIGHT, STRIDE, DST_COLOR); + + data->render_copy(data->batch, NULL, + &src, 0, 0, WIDTH, HEIGHT, + &dst, WIDTH, HEIGHT); + + scratch_buf_init(&local, &local_src, WIDTH, HEIGHT, STRIDE, 0); + scratch_buf_init(&local, &local_dst, WIDTH, HEIGHT, STRIDE, SRC_COLOR); + + local.render_copy(local.batch, NULL, + &local_src, 0, 0, WIDTH, HEIGHT, + &local_dst, WIDTH, HEIGHT); + + + drm_intel_bo_flink(local_dst.bo, &name); + flink = local_dst; + flink.bo = drm_intel_bo_gem_create_from_name(data->bufmgr, "flink", name); + + data->render_copy(data->batch, NULL, + &flink, 0, 0, WIDTH, HEIGHT, + &dst, WIDTH / 2, HEIGHT / 2); + + scratch_buf_check(data, &dst, 10, 10, DST_COLOR); + scratch_buf_check(data, &dst, WIDTH - 10, HEIGHT - 10, SRC_COLOR); + + scratch_buf_check(data, &dst, 10, 10, DST_COLOR); + scratch_buf_check(data, &dst, WIDTH - 10, HEIGHT - 10, SRC_COLOR); + + scratch_buf_fini(data, &src); + scratch_buf_fini(data, &flink); + scratch_buf_fini(data, &dst); + + scratch_buf_fini(&local, &local_src); + scratch_buf_fini(&local, &local_dst); + + data_fini(&local); +} + +int main(int argc, char **argv) +{ + data_t data = {0, }; + + igt_subtest_init(argc, argv); + + igt_fixture { + data_init(&data); + } + + igt_subtest("normal") { + int loop = 100; + while (loop--) + copy(&data); + } + + igt_subtest("interruptible") { + int loop = 100; + igt_fork_signal_helper(); + while (loop--) + copy(&data); + igt_stop_signal_helper(); + } + + igt_subtest("flink") { + int loop = 100; + while (loop--) + copy_flink(&data); + } + + igt_subtest("flink-interruptible") { + int loop = 100; + igt_fork_signal_helper(); + while (loop--) + copy_flink(&data); + igt_stop_signal_helper(); + } + + igt_exit(); + + return 0; +} diff --git a/tests/gem_render_linear_blits.c b/tests/gem_render_linear_blits.c new file mode 100644 index 00000000..fd7c2be2 --- /dev/null +++ b/tests/gem_render_linear_blits.c @@ -0,0 +1,205 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Chris Wilson <chris@chris-wilson.co.uk> + * + */ + +/** @file gem_linear_render_blits.c + * + * This is a test of doing many blits, with a working set + * larger than the aperture size. + * + * The goal is to simply ensure the basics work. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <getopt.h> + +#include <drm.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_io.h" +#include "intel_chipset.h" +#include "igt_aux.h" + +#define WIDTH 512 +#define STRIDE (WIDTH*4) +#define HEIGHT 512 +#define SIZE (HEIGHT*STRIDE) + +static uint32_t linear[WIDTH*HEIGHT]; +static igt_render_copyfunc_t render_copy; + +static void +check_bo(int fd, uint32_t handle, uint32_t val) +{ + int i; + + gem_read(fd, handle, 0, linear, sizeof(linear)); + for (i = 0; i < WIDTH*HEIGHT; i++) { + igt_assert_f(linear[i] == val, + "Expected 0x%08x, found 0x%08x " + "at offset 0x%08x\n", + val, linear[i], i * 4); + val++; + } +} + +int main(int argc, char **argv) +{ + drm_intel_bufmgr *bufmgr; + struct intel_batchbuffer *batch; + uint32_t *start_val; + drm_intel_bo **bo; + uint32_t start = 0; + int i, j, fd, count; + + igt_simple_init(); + + fd = drm_open_any(); + + render_copy = igt_get_render_copyfunc(intel_get_drm_devid(fd)); + igt_require(render_copy); + + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); + + count = 0; + if (igt_run_in_simulation()) + count = 2; + if (argc > 1) + count = atoi(argv[1]); + + if (count == 0) + count = 3 * gem_aperture_size(fd) / SIZE / 2; + else if (count < 2) { + fprintf(stderr, "count must be >= 2\n"); + return 1; + } + + if (count > intel_get_total_ram_mb() * 9 / 10) { + count = intel_get_total_ram_mb() * 9 / 10; + igt_info("not enough RAM to run test, reducing buffer count\n"); + } + + bo = malloc(sizeof(*bo)*count); + start_val = malloc(sizeof(*start_val)*count); + + for (i = 0; i < count; i++) { + bo[i] = drm_intel_bo_alloc(bufmgr, "", SIZE, 4096); + start_val[i] = start; + for (j = 0; j < WIDTH*HEIGHT; j++) + linear[j] = start++; + gem_write(fd, bo[i]->handle, 0, linear, sizeof(linear)); + } + + igt_info("Verifying initialisation...\n"); + for (i = 0; i < count; i++) + check_bo(fd, bo[i]->handle, start_val[i]); + + igt_info("Cyclic blits, forward...\n"); + for (i = 0; i < count * 4; i++) { + struct igt_buf src, dst; + + src.bo = bo[i % count]; + src.stride = STRIDE; + src.tiling = I915_TILING_NONE; + src.size = SIZE; + + dst.bo = bo[(i + 1) % count]; + dst.stride = STRIDE; + dst.tiling = I915_TILING_NONE; + dst.size = SIZE; + + render_copy(batch, NULL, &src, 0, 0, WIDTH, HEIGHT, &dst, 0, 0); + start_val[(i + 1) % count] = start_val[i % count]; + } + for (i = 0; i < count; i++) + check_bo(fd, bo[i]->handle, start_val[i]); + + if (igt_run_in_simulation()) + return 0; + + igt_info("Cyclic blits, backward...\n"); + for (i = 0; i < count * 4; i++) { + struct igt_buf src, dst; + + src.bo = bo[(i + 1) % count]; + src.stride = STRIDE; + src.tiling = I915_TILING_NONE; + src.size = SIZE; + + dst.bo = bo[i % count]; + dst.stride = STRIDE; + dst.tiling = I915_TILING_NONE; + dst.size = SIZE; + + render_copy(batch, NULL, &src, 0, 0, WIDTH, HEIGHT, &dst, 0, 0); + start_val[i % count] = start_val[(i + 1) % count]; + } + for (i = 0; i < count; i++) + check_bo(fd, bo[i]->handle, start_val[i]); + + igt_info("Random blits...\n"); + for (i = 0; i < count * 4; i++) { + struct igt_buf src, dst; + int s = random() % count; + int d = random() % count; + + if (s == d) + continue; + + src.bo = bo[s]; + src.stride = STRIDE; + src.tiling = I915_TILING_NONE; + src.size = SIZE; + + dst.bo = bo[d]; + dst.stride = STRIDE; + dst.tiling = I915_TILING_NONE; + dst.size = SIZE; + + render_copy(batch, NULL, &src, 0, 0, WIDTH, HEIGHT, &dst, 0, 0); + start_val[d] = start_val[s]; + } + for (i = 0; i < count; i++) + check_bo(fd, bo[i]->handle, start_val[i]); + + return 0; +} diff --git a/tests/gem_render_tiled_blits.c b/tests/gem_render_tiled_blits.c new file mode 100644 index 00000000..8b74e2b4 --- /dev/null +++ b/tests/gem_render_tiled_blits.c @@ -0,0 +1,216 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Chris Wilson <chris@chris-wilson.co.uk> + * + */ + +/** @file gem_linear_render_blits.c + * + * This is a test of doing many blits, with a working set + * larger than the aperture size. + * + * The goal is to simply ensure the basics work. + */ + +#include <stdlib.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <getopt.h> + +#include <drm.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_io.h" +#include "intel_chipset.h" +#include "igt_aux.h" + +#define WIDTH 512 +#define STRIDE (WIDTH*4) +#define HEIGHT 512 +#define SIZE (HEIGHT*STRIDE) + +static igt_render_copyfunc_t render_copy; +static drm_intel_bo *linear; +static uint32_t data[WIDTH*HEIGHT]; +static int snoop; + +static void +check_bo(struct intel_batchbuffer *batch, struct igt_buf *buf, uint32_t val) +{ + struct igt_buf tmp; + uint32_t *ptr; + int i; + + tmp.bo = linear; + tmp.stride = STRIDE; + tmp.tiling = I915_TILING_NONE; + tmp.size = SIZE; + + render_copy(batch, NULL, buf, 0, 0, WIDTH, HEIGHT, &tmp, 0, 0); + if (snoop) { + do_or_die(dri_bo_map(linear, 0)); + ptr = linear->virtual; + } else { + do_or_die(drm_intel_bo_get_subdata(linear, 0, sizeof(data), data)); + ptr = data; + } + for (i = 0; i < WIDTH*HEIGHT; i++) { + igt_assert_f(ptr[i] == val, + "Expected 0x%08x, found 0x%08x " + "at offset 0x%08x\n", + val, ptr[i], i * 4); + val++; + } + if (ptr != data) + dri_bo_unmap(linear); +} + +int main(int argc, char **argv) +{ + drm_intel_bufmgr *bufmgr; + struct intel_batchbuffer *batch; + uint32_t *start_val; + struct igt_buf *buf; + uint32_t start = 0; + int i, j, fd, count; + uint32_t devid; + + igt_simple_init(); + + igt_skip_on_simulation(); + + fd = drm_open_any(); + devid = intel_get_drm_devid(fd); + + render_copy = igt_get_render_copyfunc(devid); + igt_require(render_copy); + + snoop = 1; + if (IS_GEN2(devid)) /* chipset only handles cached -> uncached */ + snoop = 0; + if (IS_BROADWATER(devid) || IS_CRESTLINE(devid)) /* snafu */ + snoop = 0; + + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + drm_intel_bufmgr_gem_set_vma_cache_size(bufmgr, 32); + batch = intel_batchbuffer_alloc(bufmgr, devid); + + count = 0; + if (argc > 1) + count = atoi(argv[1]); + if (count == 0) + count = 3 * gem_aperture_size(fd) / SIZE / 2; + else if (count < 2) { + fprintf(stderr, "count must be >= 2\n"); + return 1; + } + + if (count > intel_get_total_ram_mb() * 9 / 10) { + count = intel_get_total_ram_mb() * 9 / 10; + igt_info("not enough RAM to run test, reducing buffer count\n"); + } + + igt_info("Using %d 1MiB buffers\n", count); + + linear = drm_intel_bo_alloc(bufmgr, "linear", WIDTH*HEIGHT*4, 0); + if (snoop) { + gem_set_caching(fd, linear->handle, 1); + igt_info("Using a snoop linear buffer for comparisons\n"); + } + + buf = malloc(sizeof(*buf)*count); + start_val = malloc(sizeof(*start_val)*count); + + for (i = 0; i < count; i++) { + uint32_t tiling = I915_TILING_X + (random() & 1); + unsigned long pitch = STRIDE; + uint32_t *ptr; + + buf[i].bo = drm_intel_bo_alloc_tiled(bufmgr, "", + WIDTH, HEIGHT, 4, + &tiling, &pitch, 0); + buf[i].stride = pitch; + buf[i].tiling = tiling; + buf[i].size = SIZE; + + start_val[i] = start; + + do_or_die(drm_intel_gem_bo_map_gtt(buf[i].bo)); + ptr = buf[i].bo->virtual; + for (j = 0; j < WIDTH*HEIGHT; j++) + ptr[j] = start++; + drm_intel_gem_bo_unmap_gtt(buf[i].bo); + } + + igt_info("Verifying initialisation...\n"); + for (i = 0; i < count; i++) + check_bo(batch, &buf[i], start_val[i]); + + igt_info("Cyclic blits, forward...\n"); + for (i = 0; i < count * 4; i++) { + int src = i % count; + int dst = (i + 1) % count; + + render_copy(batch, NULL, buf+src, 0, 0, WIDTH, HEIGHT, buf+dst, 0, 0); + start_val[dst] = start_val[src]; + } + for (i = 0; i < count; i++) + check_bo(batch, &buf[i], start_val[i]); + + igt_info("Cyclic blits, backward...\n"); + for (i = 0; i < count * 4; i++) { + int src = (i + 1) % count; + int dst = i % count; + + render_copy(batch, NULL, buf+src, 0, 0, WIDTH, HEIGHT, buf+dst, 0, 0); + start_val[dst] = start_val[src]; + } + for (i = 0; i < count; i++) + check_bo(batch, &buf[i], start_val[i]); + + igt_info("Random blits...\n"); + for (i = 0; i < count * 4; i++) { + int src = random() % count; + int dst = random() % count; + + if (src == dst) + continue; + + render_copy(batch, NULL, buf+src, 0, 0, WIDTH, HEIGHT, buf+dst, 0, 0); + start_val[dst] = start_val[src]; + } + for (i = 0; i < count; i++) + check_bo(batch, &buf[i], start_val[i]); + + return 0; +} diff --git a/tests/gem_reset_stats.c b/tests/gem_reset_stats.c new file mode 100644 index 00000000..3f5a01f8 --- /dev/null +++ b/tests/gem_reset_stats.c @@ -0,0 +1,1163 @@ +/* + * Copyright (c) 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Mika Kuoppala <mika.kuoppala@intel.com> + * + */ + +#define _GNU_SOURCE +#include <stdbool.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <time.h> +#include <signal.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "igt_debugfs.h" +#include "intel_chipset.h" +#include "intel_io.h" +#include "igt_aux.h" + +#define RS_NO_ERROR 0 +#define RS_BATCH_ACTIVE (1 << 0) +#define RS_BATCH_PENDING (1 << 1) +#define RS_UNKNOWN (1 << 2) + +static uint32_t devid; +static bool hw_contexts; + +struct local_drm_i915_reset_stats { + __u32 ctx_id; + __u32 flags; + __u32 reset_count; + __u32 batch_active; + __u32 batch_pending; + __u32 pad; +}; + +struct local_drm_i915_gem_context_create { + __u32 ctx_id; + __u32 pad; +}; + +struct local_drm_i915_gem_context_destroy { + __u32 ctx_id; + __u32 pad; +}; + +#define MAX_FD 32 + +#define CONTEXT_CREATE_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x2d, struct local_drm_i915_gem_context_create) +#define CONTEXT_DESTROY_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x2e, struct local_drm_i915_gem_context_destroy) +#define GET_RESET_STATS_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x32, struct local_drm_i915_reset_stats) + +#define LOCAL_I915_EXEC_VEBOX (4 << 0) + +struct target_ring; + +static bool gem_has_render(int fd) +{ + return true; +} + +static bool has_context(const struct target_ring *ring); + +static const struct target_ring { + uint32_t exec; + bool (*present)(int fd); + bool (*contexts)(const struct target_ring *ring); + const char *name; +} rings[] = { + { I915_EXEC_RENDER, gem_has_render, has_context, "render" }, + { I915_EXEC_BLT, gem_has_blt, has_context, "blt" }, + { I915_EXEC_BSD, gem_has_bsd, has_context, "bsd" }, + { LOCAL_I915_EXEC_VEBOX, gem_has_vebox, has_context, "vebox" }, +}; + +static bool has_context(const struct target_ring *ring) +{ + if (!hw_contexts) + return false; + + if(ring->exec == I915_EXEC_RENDER) + return true; + + return false; +} + +#define NUM_RINGS (sizeof(rings)/sizeof(struct target_ring)) + +static const struct target_ring *current_ring; + +static uint32_t context_create(int fd) +{ + struct local_drm_i915_gem_context_create create; + int ret; + + create.ctx_id = rand(); + create.pad = rand(); + + ret = drmIoctl(fd, CONTEXT_CREATE_IOCTL, &create); + igt_assert(ret == 0); + + return create.ctx_id; +} + +static int context_destroy(int fd, uint32_t ctx_id) +{ + int ret; + struct local_drm_i915_gem_context_destroy destroy; + + destroy.ctx_id = ctx_id; + destroy.pad = rand(); + + ret = drmIoctl(fd, CONTEXT_DESTROY_IOCTL, &destroy); + if (ret != 0) + return -errno; + + return 0; +} + +static int gem_reset_stats(int fd, int ctx_id, + struct local_drm_i915_reset_stats *rs) +{ + int ret; + + rs->ctx_id = ctx_id; + rs->flags = 0; + rs->reset_count = rand(); + rs->batch_active = rand(); + rs->batch_pending = rand(); + rs->pad = 0; + + do { + ret = ioctl(fd, GET_RESET_STATS_IOCTL, rs); + } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); + + if (ret < 0) + return -errno; + + return 0; +} + +static int gem_reset_status(int fd, int ctx_id) +{ + int ret; + struct local_drm_i915_reset_stats rs; + + ret = gem_reset_stats(fd, ctx_id, &rs); + if (ret) + return ret; + + if (rs.batch_active) + return RS_BATCH_ACTIVE; + if (rs.batch_pending) + return RS_BATCH_PENDING; + + return RS_NO_ERROR; +} + +static int gem_exec(int fd, struct drm_i915_gem_execbuffer2 *execbuf) +{ + int ret; + + ret = ioctl(fd, + DRM_IOCTL_I915_GEM_EXECBUFFER2, + execbuf); + + if (ret < 0) + return -errno; + + return 0; +} + +static int exec_valid_ring(int fd, int ctx, int ring) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 exec; + int ret; + + uint32_t buf[2] = { MI_BATCH_BUFFER_END, 0 }; + + exec.handle = gem_create(fd, 4096); + gem_write(fd, exec.handle, 0, buf, sizeof(buf)); + exec.relocation_count = 0; + exec.relocs_ptr = 0; + exec.alignment = 0; + exec.offset = 0; + exec.flags = 0; + exec.rsvd1 = 0; + exec.rsvd2 = 0; + + execbuf.buffers_ptr = (uintptr_t)&exec; + execbuf.buffer_count = 1; + execbuf.batch_start_offset = 0; + execbuf.batch_len = sizeof(buf); + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = ring; + i915_execbuffer2_set_context_id(execbuf, ctx); + execbuf.rsvd2 = 0; + + ret = gem_exec(fd, &execbuf); + if (ret < 0) + return ret; + + return exec.handle; +} + +static int exec_valid(int fd, int ctx) +{ + return exec_valid_ring(fd, ctx, current_ring->exec); +} + +#define BUFSIZE (4 * 1024) +#define ITEMS (BUFSIZE >> 2) + +static int inject_hang_ring(int fd, int ctx, int ring, bool ignore_ban_error) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 exec; + uint64_t gtt_off; + uint32_t *buf; + int roff, i; + unsigned cmd_len = 2; + enum stop_ring_flags flags; + + srandom(time(NULL)); + + if (intel_gen(devid) >= 8) + cmd_len = 3; + + buf = malloc(BUFSIZE); + igt_assert(buf != NULL); + + buf[0] = MI_BATCH_BUFFER_END; + buf[1] = MI_NOOP; + + exec.handle = gem_create(fd, BUFSIZE); + gem_write(fd, exec.handle, 0, buf, BUFSIZE); + exec.relocation_count = 0; + exec.relocs_ptr = 0; + exec.alignment = 0; + exec.offset = 0; + exec.flags = 0; + exec.rsvd1 = 0; + exec.rsvd2 = 0; + + execbuf.buffers_ptr = (uintptr_t)&exec; + execbuf.buffer_count = 1; + execbuf.batch_start_offset = 0; + execbuf.batch_len = BUFSIZE; + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = ring; + i915_execbuffer2_set_context_id(execbuf, ctx); + execbuf.rsvd2 = 0; + + igt_assert(gem_exec(fd, &execbuf) == 0); + + gtt_off = exec.offset; + + for (i = 0; i < ITEMS; i++) + buf[i] = MI_NOOP; + + roff = random() % (ITEMS - cmd_len - 1); + buf[roff] = MI_BATCH_BUFFER_START | (cmd_len - 2); + buf[roff + 1] = (gtt_off & 0xfffffffc) + (roff << 2); + if (cmd_len == 3) + buf[roff + 2] = (gtt_off & 0xffffffff00000000ull) >> 32; + + buf[roff + cmd_len] = MI_BATCH_BUFFER_END; + + igt_debug("loop injected at 0x%lx (off 0x%x, bo_start 0x%lx, bo_end 0x%lx)\n", + (long unsigned int)((roff << 2) + gtt_off), + roff << 2, (long unsigned int)gtt_off, + (long unsigned int)(gtt_off + BUFSIZE - 1)); + gem_write(fd, exec.handle, 0, buf, BUFSIZE); + + exec.relocation_count = 0; + exec.relocs_ptr = 0; + exec.alignment = 0; + exec.offset = 0; + exec.flags = 0; + exec.rsvd1 = 0; + exec.rsvd2 = 0; + + execbuf.buffers_ptr = (uintptr_t)&exec; + execbuf.buffer_count = 1; + execbuf.batch_start_offset = 0; + execbuf.batch_len = BUFSIZE; + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = ring; + i915_execbuffer2_set_context_id(execbuf, ctx); + execbuf.rsvd2 = 0; + + igt_assert(gem_exec(fd, &execbuf) == 0); + + igt_assert(gtt_off == exec.offset); + + free(buf); + + flags = igt_to_stop_ring_flag(ring); + + flags |= STOP_RING_ALLOW_BAN; + + if (!ignore_ban_error) + flags |= STOP_RING_ALLOW_ERRORS; + + igt_set_stop_rings(flags); + + return exec.handle; +} + +static int inject_hang(int fd, int ctx) +{ + return inject_hang_ring(fd, ctx, current_ring->exec, false); +} + +static int inject_hang_no_ban_error(int fd, int ctx) +{ + return inject_hang_ring(fd, ctx, current_ring->exec, true); +} + +static int _assert_reset_status(int fd, int ctx, int status) +{ + int rs; + + rs = gem_reset_status(fd, ctx); + if (rs < 0) { + igt_info("reset status for %d ctx %d returned %d\n", + fd, ctx, rs); + return rs; + } + + if (rs != status) { + igt_info("%d:%d reset status %d differs from assumed %d\n", + fd, ctx, rs, status); + + return 1; + } + + return 0; +} + +#define assert_reset_status(fd, ctx, status) \ + igt_assert(_assert_reset_status(fd, ctx, status) == 0) + +static void test_rs(int num_fds, int hang_index, int rs_assumed_no_hang) +{ + int i; + int fd[MAX_FD]; + int h[MAX_FD]; + + igt_assert (num_fds <= MAX_FD); + igt_assert (hang_index < MAX_FD); + + for (i = 0; i < num_fds; i++) { + fd[i] = drm_open_any(); + igt_assert(fd[i]); + } + + for (i = 0; i < num_fds; i++) + assert_reset_status(fd[i], 0, RS_NO_ERROR); + + for (i = 0; i < num_fds; i++) { + if (i == hang_index) + h[i] = inject_hang(fd[i], 0); + else + h[i] = exec_valid(fd[i], 0); + } + + gem_sync(fd[num_fds - 1], h[num_fds - 1]); + + for (i = 0; i < num_fds; i++) { + if (hang_index < 0) { + assert_reset_status(fd[i], 0, rs_assumed_no_hang); + continue; + } + + if (i < hang_index) + assert_reset_status(fd[i], 0, RS_NO_ERROR); + if (i == hang_index) + assert_reset_status(fd[i], 0, RS_BATCH_ACTIVE); + if (i > hang_index) + assert_reset_status(fd[i], 0, RS_BATCH_PENDING); + } + + for (i = 0; i < num_fds; i++) { + gem_close(fd[i], h[i]); + close(fd[i]); + } +} + +#define MAX_CTX 100 +static void test_rs_ctx(int num_fds, int num_ctx, int hang_index, + int hang_context) +{ + int i, j; + int fd[MAX_FD]; + int h[MAX_FD][MAX_CTX]; + int ctx[MAX_FD][MAX_CTX]; + + igt_assert (num_fds <= MAX_FD); + igt_assert (hang_index < MAX_FD); + + igt_assert (num_ctx <= MAX_CTX); + igt_assert (hang_context < MAX_CTX); + + test_rs(num_fds, -1, RS_NO_ERROR); + + for (i = 0; i < num_fds; i++) { + fd[i] = drm_open_any(); + igt_assert(fd[i]); + assert_reset_status(fd[i], 0, RS_NO_ERROR); + + for (j = 0; j < num_ctx; j++) { + ctx[i][j] = context_create(fd[i]); + + } + + assert_reset_status(fd[i], 0, RS_NO_ERROR); + } + + for (i = 0; i < num_fds; i++) { + + assert_reset_status(fd[i], 0, RS_NO_ERROR); + + for (j = 0; j < num_ctx; j++) + assert_reset_status(fd[i], ctx[i][j], RS_NO_ERROR); + + assert_reset_status(fd[i], 0, RS_NO_ERROR); + } + + for (i = 0; i < num_fds; i++) { + for (j = 0; j < num_ctx; j++) { + if (i == hang_index && j == hang_context) + h[i][j] = inject_hang(fd[i], ctx[i][j]); + else + h[i][j] = exec_valid(fd[i], ctx[i][j]); + } + } + + gem_sync(fd[num_fds - 1], ctx[num_fds - 1][num_ctx - 1]); + + for (i = 0; i < num_fds; i++) + assert_reset_status(fd[i], 0, RS_NO_ERROR); + + for (i = 0; i < num_fds; i++) { + for (j = 0; j < num_ctx; j++) { + if (i < hang_index) + assert_reset_status(fd[i], ctx[i][j], RS_NO_ERROR); + if (i == hang_index && j < hang_context) + assert_reset_status(fd[i], ctx[i][j], RS_NO_ERROR); + if (i == hang_index && j == hang_context) + assert_reset_status(fd[i], ctx[i][j], + RS_BATCH_ACTIVE); + if (i == hang_index && j > hang_context) + assert_reset_status(fd[i], ctx[i][j], + RS_BATCH_PENDING); + if (i > hang_index) + assert_reset_status(fd[i], ctx[i][j], + RS_BATCH_PENDING); + } + } + + for (i = 0; i < num_fds; i++) { + for (j = 0; j < num_ctx; j++) { + gem_close(fd[i], h[i][j]); + igt_assert(context_destroy(fd[i], ctx[i][j]) == 0); + } + + assert_reset_status(fd[i], 0, RS_NO_ERROR); + + close(fd[i]); + } +} + +static void test_ban(void) +{ + int h1,h2,h3,h4,h5,h6,h7; + int fd_bad, fd_good; + int retry = 10; + int active_count = 0, pending_count = 0; + struct local_drm_i915_reset_stats rs_bad, rs_good; + + fd_bad = drm_open_any(); + igt_assert(fd_bad >= 0); + + fd_good = drm_open_any(); + igt_assert(fd_good >= 0); + + assert_reset_status(fd_bad, 0, RS_NO_ERROR); + assert_reset_status(fd_good, 0, RS_NO_ERROR); + + h1 = exec_valid(fd_bad, 0); + igt_assert(h1 >= 0); + h5 = exec_valid(fd_good, 0); + igt_assert(h5 >= 0); + + assert_reset_status(fd_bad, 0, RS_NO_ERROR); + assert_reset_status(fd_good, 0, RS_NO_ERROR); + + h2 = inject_hang_no_ban_error(fd_bad, 0); + igt_assert(h2 >= 0); + active_count++; + /* Second hang will be pending for this */ + pending_count++; + + h6 = exec_valid(fd_good, 0); + h7 = exec_valid(fd_good, 0); + + while (retry--) { + h3 = inject_hang_no_ban_error(fd_bad, 0); + igt_assert(h3 >= 0); + gem_sync(fd_bad, h3); + active_count++; + /* This second hand will count as pending */ + assert_reset_status(fd_bad, 0, RS_BATCH_ACTIVE); + + h4 = exec_valid(fd_bad, 0); + if (h4 == -EIO) { + gem_close(fd_bad, h3); + break; + } + + /* Should not happen often but sometimes hang is declared too slow + * due to our way of faking hang using loop */ + + igt_assert(h4 >= 0); + gem_close(fd_bad, h3); + gem_close(fd_bad, h4); + + igt_info("retrying for ban (%d)\n", retry); + } + + igt_assert(h4 == -EIO); + assert_reset_status(fd_bad, 0, RS_BATCH_ACTIVE); + + gem_sync(fd_good, h7); + assert_reset_status(fd_good, 0, RS_BATCH_PENDING); + + igt_assert(gem_reset_stats(fd_good, 0, &rs_good) == 0); + igt_assert(gem_reset_stats(fd_bad, 0, &rs_bad) == 0); + + igt_assert(rs_bad.batch_active == active_count); + igt_assert(rs_bad.batch_pending == pending_count); + igt_assert(rs_good.batch_active == 0); + igt_assert(rs_good.batch_pending == 2); + + gem_close(fd_bad, h1); + gem_close(fd_bad, h2); + gem_close(fd_good, h6); + gem_close(fd_good, h7); + + h1 = exec_valid(fd_good, 0); + igt_assert(h1 >= 0); + gem_close(fd_good, h1); + + close(fd_bad); + close(fd_good); + + igt_assert(gem_reset_status(fd_bad, 0) < 0); + igt_assert(gem_reset_status(fd_good, 0) < 0); +} + +static void test_ban_ctx(void) +{ + int h1,h2,h3,h4,h5,h6,h7; + int ctx_good, ctx_bad; + int fd; + int retry = 10; + int active_count = 0, pending_count = 0; + struct local_drm_i915_reset_stats rs_bad, rs_good; + + fd = drm_open_any(); + igt_assert(fd >= 0); + + assert_reset_status(fd, 0, RS_NO_ERROR); + + ctx_good = context_create(fd); + ctx_bad = context_create(fd); + + assert_reset_status(fd, 0, RS_NO_ERROR); + assert_reset_status(fd, ctx_good, RS_NO_ERROR); + assert_reset_status(fd, ctx_bad, RS_NO_ERROR); + + h1 = exec_valid(fd, ctx_bad); + igt_assert(h1 >= 0); + h5 = exec_valid(fd, ctx_good); + igt_assert(h5 >= 0); + + assert_reset_status(fd, ctx_good, RS_NO_ERROR); + assert_reset_status(fd, ctx_bad, RS_NO_ERROR); + + h2 = inject_hang_no_ban_error(fd, ctx_bad); + igt_assert(h2 >= 0); + active_count++; + /* Second hang will be pending for this */ + pending_count++; + + h6 = exec_valid(fd, ctx_good); + h7 = exec_valid(fd, ctx_good); + + while (retry--) { + h3 = inject_hang_no_ban_error(fd, ctx_bad); + igt_assert(h3 >= 0); + gem_sync(fd, h3); + active_count++; + /* This second hand will count as pending */ + assert_reset_status(fd, ctx_bad, RS_BATCH_ACTIVE); + + h4 = exec_valid(fd, ctx_bad); + if (h4 == -EIO) { + gem_close(fd, h3); + break; + } + + /* Should not happen often but sometimes hang is declared too slow + * due to our way of faking hang using loop */ + + igt_assert(h4 >= 0); + gem_close(fd, h3); + gem_close(fd, h4); + + igt_info("retrying for ban (%d)\n", retry); + } + + igt_assert(h4 == -EIO); + assert_reset_status(fd, ctx_bad, RS_BATCH_ACTIVE); + + gem_sync(fd, h7); + assert_reset_status(fd, ctx_good, RS_BATCH_PENDING); + + igt_assert(gem_reset_stats(fd, ctx_good, &rs_good) == 0); + igt_assert(gem_reset_stats(fd, ctx_bad, &rs_bad) == 0); + + igt_assert(rs_bad.batch_active == active_count); + igt_assert(rs_bad.batch_pending == pending_count); + igt_assert(rs_good.batch_active == 0); + igt_assert(rs_good.batch_pending == 2); + + gem_close(fd, h1); + gem_close(fd, h2); + gem_close(fd, h6); + gem_close(fd, h7); + + h1 = exec_valid(fd, ctx_good); + igt_assert(h1 >= 0); + gem_close(fd, h1); + + igt_assert(context_destroy(fd, ctx_good) == 0); + igt_assert(context_destroy(fd, ctx_bad) == 0); + igt_assert(gem_reset_status(fd, ctx_good) < 0); + igt_assert(gem_reset_status(fd, ctx_bad) < 0); + igt_assert(exec_valid(fd, ctx_good) < 0); + igt_assert(exec_valid(fd, ctx_bad) < 0); + + close(fd); +} + +static void test_unrelated_ctx(void) +{ + int h1,h2; + int fd1,fd2; + int ctx_guilty, ctx_unrelated; + + fd1 = drm_open_any(); + fd2 = drm_open_any(); + assert_reset_status(fd1, 0, RS_NO_ERROR); + assert_reset_status(fd2, 0, RS_NO_ERROR); + ctx_guilty = context_create(fd1); + ctx_unrelated = context_create(fd2); + + assert_reset_status(fd1, ctx_guilty, RS_NO_ERROR); + assert_reset_status(fd2, ctx_unrelated, RS_NO_ERROR); + + h1 = inject_hang(fd1, ctx_guilty); + igt_assert(h1 >= 0); + gem_sync(fd1, h1); + assert_reset_status(fd1, ctx_guilty, RS_BATCH_ACTIVE); + assert_reset_status(fd2, ctx_unrelated, RS_NO_ERROR); + + h2 = exec_valid(fd2, ctx_unrelated); + igt_assert(h2 >= 0); + gem_sync(fd2, h2); + assert_reset_status(fd1, ctx_guilty, RS_BATCH_ACTIVE); + assert_reset_status(fd2, ctx_unrelated, RS_NO_ERROR); + gem_close(fd1, h1); + gem_close(fd2, h2); + + igt_assert(context_destroy(fd1, ctx_guilty) == 0); + igt_assert(context_destroy(fd2, ctx_unrelated) == 0); + + close(fd1); + close(fd2); +} + +static int get_reset_count(int fd, int ctx) +{ + int ret; + struct local_drm_i915_reset_stats rs; + + ret = gem_reset_stats(fd, ctx, &rs); + if (ret) + return ret; + + return rs.reset_count; +} + +static void test_close_pending_ctx(void) +{ + int fd, h; + uint32_t ctx; + + fd = drm_open_any(); + igt_assert(fd >= 0); + ctx = context_create(fd); + + assert_reset_status(fd, ctx, RS_NO_ERROR); + + h = inject_hang(fd, ctx); + igt_assert(h >= 0); + igt_assert(context_destroy(fd, ctx) == 0); + igt_assert(context_destroy(fd, ctx) == -ENOENT); + + gem_close(fd, h); + close(fd); +} + +static void test_close_pending(void) +{ + int fd, h; + + fd = drm_open_any(); + igt_assert(fd >= 0); + + assert_reset_status(fd, 0, RS_NO_ERROR); + + h = inject_hang(fd, 0); + igt_assert(h >= 0); + + gem_close(fd, h); + close(fd); +} + +static void exec_noop_on_each_ring(int fd, const bool reverse) +{ + uint32_t batch[2] = {MI_BATCH_BUFFER_END, 0}; + uint32_t handle; + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 exec[1]; + + handle = gem_create(fd, 4096); + gem_write(fd, handle, 0, batch, sizeof(batch)); + + exec[0].handle = handle; + exec[0].relocation_count = 0; + exec[0].relocs_ptr = 0; + exec[0].alignment = 0; + exec[0].offset = 0; + exec[0].flags = 0; + exec[0].rsvd1 = 0; + exec[0].rsvd2 = 0; + + execbuf.buffers_ptr = (uintptr_t)exec; + execbuf.buffer_count = 1; + execbuf.batch_start_offset = 0; + execbuf.batch_len = 8; + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = 0; + i915_execbuffer2_set_context_id(execbuf, 0); + execbuf.rsvd2 = 0; + + for (unsigned i = 0; i < NUM_RINGS; i++) { + const struct target_ring *ring; + + ring = reverse ? &rings[NUM_RINGS - 1 - i] : &rings[i]; + + if (ring->present(fd)) { + execbuf.flags = ring->exec; + do_ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + } + } + + gem_sync(fd, handle); + gem_close(fd, handle); +} + +static void test_close_pending_fork(const bool reverse) +{ + int pid; + int fd, h; + + fd = drm_open_any(); + igt_assert(fd >= 0); + + assert_reset_status(fd, 0, RS_NO_ERROR); + + h = inject_hang(fd, 0); + igt_assert(h >= 0); + + sleep(1); + + /* Avoid helpers as we need to kill the child + * without any extra signal handling on behalf of + * lib/drmtest.c + */ + pid = fork(); + if (pid == 0) { + const int fd2 = drm_open_any(); + igt_assert(fd2 >= 0); + + /* The crucial component is that we schedule the same noop batch + * on each ring. This exercises batch_obj reference counting, + * when gpu is reset and ring lists are cleared. + */ + exec_noop_on_each_ring(fd2, reverse); + + close(fd2); + return; + } else { + igt_assert(pid > 0); + sleep(1); + + /* Kill the child to reduce refcounts on + batch_objs */ + kill(pid, SIGKILL); + } + + gem_close(fd, h); + close(fd); + + /* Then we just wait on hang to happen */ + fd = drm_open_any(); + igt_assert(fd >= 0); + + h = exec_valid(fd, 0); + igt_assert(h >= 0); + + gem_sync(fd, h); + gem_close(fd, h); + close(fd); +} + +static void test_reset_count(const bool create_ctx) +{ + int fd, h, ctx; + long c1, c2; + + fd = drm_open_any(); + igt_assert(fd >= 0); + if (create_ctx) + ctx = context_create(fd); + else + ctx = 0; + + assert_reset_status(fd, ctx, RS_NO_ERROR); + + c1 = get_reset_count(fd, ctx); + igt_assert(c1 >= 0); + + h = inject_hang(fd, ctx); + igt_assert (h >= 0); + gem_sync(fd, h); + + assert_reset_status(fd, ctx, RS_BATCH_ACTIVE); + c2 = get_reset_count(fd, ctx); + igt_assert(c2 >= 0); + igt_assert(c2 == (c1 + 1)); + + igt_fork(child, 1) { + igt_drop_root(); + + c2 = get_reset_count(fd, ctx); + + if (ctx == 0) + igt_assert(c2 == -EPERM); + else + igt_assert(c2 == 0); + } + + igt_waitchildren(); + + gem_close(fd, h); + + if (create_ctx) + context_destroy(fd, ctx); + + close(fd); +} + +static int _test_params(int fd, int ctx, uint32_t flags, uint32_t pad) +{ + struct local_drm_i915_reset_stats rs; + int ret; + + rs.ctx_id = ctx; + rs.flags = flags; + rs.reset_count = rand(); + rs.batch_active = rand(); + rs.batch_pending = rand(); + rs.pad = pad; + + do { + ret = ioctl(fd, GET_RESET_STATS_IOCTL, &rs); + } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); + + if (ret < 0) + return -errno; + + return 0; +} + +typedef enum { root = 0, user } cap_t; + +static void _check_param_ctx(const int fd, const int ctx, const cap_t cap) +{ + const uint32_t bad = rand() + 1; + + if (ctx == 0) { + if (cap == root) + igt_assert(_test_params(fd, ctx, 0, 0) == 0); + else + igt_assert(_test_params(fd, ctx, 0, 0) == -EPERM); + } + + igt_assert(_test_params(fd, ctx, 0, bad) == -EINVAL); + igt_assert(_test_params(fd, ctx, bad, 0) == -EINVAL); + igt_assert(_test_params(fd, ctx, bad, bad) == -EINVAL); +} + +static void check_params(const int fd, const int ctx, cap_t cap) +{ + igt_assert(ioctl(fd, GET_RESET_STATS_IOCTL, 0) == -1); + igt_assert(_test_params(fd, 0xbadbad, 0, 0) == -ENOENT); + + _check_param_ctx(fd, ctx, cap); +} + +static void _test_param(const int fd, const int ctx) +{ + check_params(fd, ctx, root); + + igt_fork(child, 1) { + check_params(fd, ctx, root); + + igt_drop_root(); + + check_params(fd, ctx, user); + } + + check_params(fd, ctx, root); + + igt_waitchildren(); +} + +static void test_params_ctx(void) +{ + int fd, ctx; + + fd = drm_open_any(); + igt_assert(fd >= 0); + ctx = context_create(fd); + + _test_param(fd, ctx); + + close(fd); +} + +static void test_params(void) +{ + int fd; + + fd = drm_open_any(); + igt_assert(fd >= 0); + + _test_param(fd, 0); + + close(fd); + +} + +static bool gem_has_hw_contexts(int fd) +{ + struct local_drm_i915_gem_context_create create; + int ret; + + memset(&create, 0, sizeof(create)); + ret = drmIoctl(fd, CONTEXT_CREATE_IOCTL, &create); + + if (ret == 0) { + drmIoctl(fd, CONTEXT_DESTROY_IOCTL, &create); + return true; + } + + return false; +} + +static bool gem_has_reset_stats(int fd) +{ + struct local_drm_i915_reset_stats rs; + int ret; + + /* Carefully set flags and pad to zero, otherwise + we get -EINVAL + */ + memset(&rs, 0, sizeof(rs)); + + ret = drmIoctl(fd, GET_RESET_STATS_IOCTL, &rs); + if (ret == 0) + return true; + + /* If we get EPERM, we have support but did not + have CAP_SYSADM */ + if (ret == -1 && errno == EPERM) + return true; + + return false; +} + +static void check_gpu_ok(void) +{ + int retry_count = 30; + enum stop_ring_flags flags; + int fd; + + igt_debug("checking gpu state\n"); + + while (retry_count--) { + flags = igt_get_stop_rings(); + if (flags == 0) + break; + + igt_debug("waiting previous hang to clear\n"); + sleep(1); + } + + igt_assert(flags == 0); + + fd = drm_open_any(); + gem_quiescent_gpu(fd); + close(fd); +} + +#define RING_HAS_CONTEXTS (current_ring->contexts(current_ring)) +#define RUN_TEST(...) do { check_gpu_ok(); __VA_ARGS__; check_gpu_ok(); } while (0) +#define RUN_CTX_TEST(...) do { igt_skip_on(RING_HAS_CONTEXTS == false); RUN_TEST(__VA_ARGS__); } while (0) + +igt_main +{ + igt_skip_on_simulation(); + + igt_fixture { + int fd; + + bool has_reset_stats; + fd = drm_open_any(); + devid = intel_get_drm_devid(fd); + + hw_contexts = gem_has_hw_contexts(fd); + has_reset_stats = gem_has_reset_stats(fd); + + close(fd); + + igt_require_f(has_reset_stats, + "No reset stats ioctl support. Too old kernel?\n"); + } + + igt_subtest("params") + test_params(); + + for (int i = 0; i < NUM_RINGS; i++) { + const char *name; + + current_ring = &rings[i]; + name = current_ring->name; + + igt_fixture { + int fd = drm_open_any(); + gem_require_ring(fd, current_ring->exec); + close(fd); + } + + igt_fixture + igt_require_f(intel_gen(devid) >= 4, + "gen %d doesn't support reset\n", intel_gen(devid)); + + igt_subtest_f("params-ctx-%s", name) + RUN_CTX_TEST(test_params_ctx()); + + igt_subtest_f("reset-stats-%s", name) + RUN_TEST(test_rs(4, 1, 0)); + + igt_subtest_f("reset-stats-ctx-%s", name) + RUN_CTX_TEST(test_rs_ctx(4, 4, 1, 2)); + + igt_subtest_f("ban-%s", name) + RUN_TEST(test_ban()); + + igt_subtest_f("ban-ctx-%s", name) + RUN_CTX_TEST(test_ban_ctx()); + + igt_subtest_f("reset-count-%s", name) + RUN_TEST(test_reset_count(false)); + + igt_subtest_f("reset-count-ctx-%s", name) + RUN_CTX_TEST(test_reset_count(true)); + + igt_subtest_f("unrelated-ctx-%s", name) + RUN_CTX_TEST(test_unrelated_ctx()); + + igt_subtest_f("close-pending-%s", name) + RUN_TEST(test_close_pending()); + + igt_subtest_f("close-pending-ctx-%s", name) + RUN_CTX_TEST(test_close_pending_ctx()); + + igt_subtest_f("close-pending-fork-%s", name) + RUN_TEST(test_close_pending_fork(false)); + + igt_subtest_f("close-pending-fork-reverse-%s", name) + RUN_TEST(test_close_pending_fork(true)); + } +} diff --git a/tests/gem_ring_sync_copy.c b/tests/gem_ring_sync_copy.c new file mode 100644 index 00000000..768d02d0 --- /dev/null +++ b/tests/gem_ring_sync_copy.c @@ -0,0 +1,368 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Damien Lespiau <damien.lespiau@intel.com> + */ + +/* + * The goal of this test is to ensure that we respect inter ring dependencies + * + * For each pair of rings R1, R2 where we have copy support (i.e. blt, + * rendercpy and mediafill) do: + * - Throw a busy load onto R1. gem_concurrent_blt just uses lots of buffers + * for this effect. + * - Fill three buffers A, B, C with unique data. + * - Copy A to B on ring R1 + * + * Then come the three different variants. + * - Copy B to C on ring R2, check that C now contains what A originally + * contained. This is the write->read hazard. gem_concurrent_blt calls this + * early read. + * - Copy C to A on ring R2, check that B now contains what A originally + * contained. This is the read->write hazard, gem_concurrent_blt calls it + * overwrite_source. + * - Copy C to B on ring R2 and check that B contains what C originally + * contained. This is the write/write hazard. gem_concurrent_blt doesn't + * have that since for the cpu case it's too boring. + * + */ + +#include <stdlib.h> +#include <stdbool.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_batchbuffer.h" +#include "intel_chipset.h" + +#define WIDTH 512 +#define HEIGHT 512 + +typedef struct { + int drm_fd; + uint32_t devid; + drm_intel_bufmgr *bufmgr; + struct intel_batchbuffer *batch; + + /* number of buffers to keep the ring busy for a while */ + unsigned int n_buffers_load; + + uint32_t linear[WIDTH * HEIGHT]; + + struct { + igt_render_copyfunc_t copy; + struct igt_buf *srcs; + struct igt_buf *dsts; + } render; + + struct { + drm_intel_bo **srcs; + drm_intel_bo **dsts; + } blitter; + +} data_t; + +enum ring { + RENDER, + BLITTER, +}; + +enum test { + TEST_WRITE_READ, + TEST_READ_WRITE, + TEST_WRITE_WRITE, +}; + +static const char *ring_name(enum ring ring) +{ + const char *names[] = { + "render", + "blitter", + }; + + return names[ring]; +} + +static drm_intel_bo *bo_create(data_t *data, int width, int height, int val) +{ + drm_intel_bo *bo; + int i; + + bo = drm_intel_bo_alloc(data->bufmgr, "", 4 * width * height, 4096); + igt_assert(bo); + + for (i = 0; i < width * height; i++) + data->linear[i] = val; + gem_write(data->drm_fd, bo->handle, 0, data->linear, + sizeof(data->linear)); + + return bo; +} + +static void bo_check(data_t *data, drm_intel_bo *bo, uint32_t val) +{ + int i; + + gem_read(data->drm_fd, bo->handle, 0, + data->linear, sizeof(data->linear)); + for (i = 0; i < WIDTH * HEIGHT; i++) + igt_assert_cmpint(data->linear[i], ==, val); +} + +static void scratch_buf_init_from_bo(struct igt_buf *buf, drm_intel_bo *bo) +{ + buf->bo = bo; + buf->stride = 4 * WIDTH; + buf->tiling = I915_TILING_NONE; + buf->size = 4 * WIDTH * HEIGHT; +} + +static void scratch_buf_init(data_t *data, struct igt_buf *buf, + int width, int height, uint32_t color) +{ + drm_intel_bo *bo; + + bo = bo_create(data, width, height, color); + scratch_buf_init_from_bo(buf, bo); +} + +/* + * Provide a few ring specific vfuncs for run_test(). + * + * busy() Queue a n_buffers_load workloads onto the ring to keep it busy + * busy_fini() Clean up after busy + * copy() Copy one BO to another + */ + +/* + * Render ring + */ + +static void render_busy(data_t *data) +{ + size_t array_size; + int i; + + array_size = data->n_buffers_load * sizeof(struct igt_buf); + data->render.srcs = malloc(array_size); + data->render.dsts = malloc(array_size); + + for (i = 0; i < data->n_buffers_load; i++) { + scratch_buf_init(data, &data->render.srcs[i], WIDTH, HEIGHT, + 0xdeadbeef); + scratch_buf_init(data, &data->render.dsts[i], WIDTH, HEIGHT, + 0xdeadbeef); + } + + for (i = 0; i < data->n_buffers_load; i++) { + data->render.copy(data->batch, + NULL, /* context */ + &data->render.srcs[i], + 0, 0, /* src_x, src_y */ + WIDTH, HEIGHT, + &data->render.dsts[i], + 0, 0 /* dst_x, dst_y */); + } +} + +static void render_busy_fini(data_t *data) +{ + int i; + + for (i = 0; i < data->n_buffers_load; i++) { + drm_intel_bo_unreference(data->render.srcs[i].bo); + drm_intel_bo_unreference(data->render.dsts[i].bo); + } + + free(data->render.srcs); + free(data->render.dsts); + data->render.srcs = NULL; + data->render.dsts = NULL; +} + +static void render_copy(data_t *data, drm_intel_bo *src, drm_intel_bo *dst) +{ + struct igt_buf src_buf, dst_buf; + + scratch_buf_init_from_bo(&src_buf, src); + scratch_buf_init_from_bo(&dst_buf, dst); + + data->render.copy(data->batch, + NULL, /* context */ + &src_buf, + 0, 0, /* src_x, src_y */ + WIDTH, HEIGHT, + &dst_buf, + 0, 0 /* dst_x, dst_y */); +} + +/* + * Blitter ring + */ + +static void blitter_busy(data_t *data) +{ + size_t array_size; + int i; + + array_size = data->n_buffers_load * sizeof(drm_intel_bo *); + data->blitter.srcs = malloc(array_size); + data->blitter.dsts = malloc(array_size); + + for (i = 0; i < data->n_buffers_load; i++) { + data->blitter.srcs[i] = bo_create(data, + WIDTH, HEIGHT, + 0xdeadbeef); + data->blitter.dsts[i] = bo_create(data, + WIDTH, HEIGHT, + 0xdeadbeef); + } + + for (i = 0; i < data->n_buffers_load; i++) { + intel_copy_bo(data->batch, + data->blitter.srcs[i], + data->blitter.dsts[i], + WIDTH*HEIGHT*4); + } +} + +static void blitter_busy_fini(data_t *data) +{ + int i; + + for (i = 0; i < data->n_buffers_load; i++) { + drm_intel_bo_unreference(data->blitter.srcs[i]); + drm_intel_bo_unreference(data->blitter.dsts[i]); + } + + free(data->blitter.srcs); + free(data->blitter.dsts); + data->blitter.srcs = NULL; + data->blitter.dsts = NULL; +} + +static void blitter_copy(data_t *data, drm_intel_bo *src, drm_intel_bo *dst) +{ + intel_copy_bo(data->batch, dst, src, WIDTH*HEIGHT*4); +} + +struct ring_ops { + void (*busy)(data_t *data); + void (*busy_fini)(data_t *data); + void (*copy)(data_t *data, drm_intel_bo *src, drm_intel_bo *dst); +} ops [] = { + { + .busy = render_busy, + .busy_fini = render_busy_fini, + .copy = render_copy, + }, + { + .busy = blitter_busy, + .busy_fini = blitter_busy_fini, + .copy = blitter_copy, + }, +}; + +static void run_test(data_t *data, enum ring r1, enum ring r2, enum test test) +{ + struct ring_ops *r1_ops = &ops[r1]; + struct ring_ops *r2_ops = &ops[r2]; + drm_intel_bo *a, *b, *c; + + a = bo_create(data, WIDTH, HEIGHT, 0xa); + b = bo_create(data, WIDTH, HEIGHT, 0xb); + c = bo_create(data, WIDTH, HEIGHT, 0xc); + + r1_ops->busy(data); + r1_ops->copy(data, a, b); + + switch (test) { + case TEST_WRITE_READ: + r2_ops->copy(data, b, c); + bo_check(data, c, 0xa); + break; + case TEST_READ_WRITE: + r2_ops->copy(data, c, a); + bo_check(data, b, 0xa); + break; + case TEST_WRITE_WRITE: + r2_ops->copy(data, c, b); + bo_check(data, b, 0xc); + break; + default: + abort(); + } + + r1_ops->busy_fini(data); +} + +igt_main +{ + data_t data = {0, }; + int i; + struct combination { + int r1, r2; + } ring_combinations [] = { + { RENDER, BLITTER }, + { BLITTER, RENDER }, + }; + + igt_fixture { + data.drm_fd = drm_open_any_render(); + data.devid = intel_get_drm_devid(data.drm_fd); + + data.n_buffers_load = 1000; + + data.bufmgr = drm_intel_bufmgr_gem_init(data.drm_fd, 4096); + igt_assert(data.bufmgr); + drm_intel_bufmgr_gem_enable_reuse(data.bufmgr); + + data.render.copy = igt_get_render_copyfunc(data.devid); + igt_require_f(data.render.copy, + "no render-copy function\n"); + + data.batch = intel_batchbuffer_alloc(data.bufmgr, data.devid); + igt_assert(data.batch); + } + + for (i = 0; i < ARRAY_SIZE(ring_combinations); i++) { + struct combination *c = &ring_combinations[i]; + + igt_subtest_f("sync-%s-%s-write-read", + ring_name(c->r1), ring_name(c->r2)) + run_test(&data, c->r1, c->r2, TEST_WRITE_READ); + + igt_subtest_f("sync-%s-%s-read-write", + ring_name(c->r1), ring_name(c->r2)) + run_test(&data, c->r1, c->r2, TEST_READ_WRITE); + igt_subtest_f("sync-%s-%s-write-write", + ring_name(c->r1), ring_name(c->r2)) + run_test(&data, c->r1, c->r2, TEST_WRITE_WRITE); + } + + igt_fixture { + intel_batchbuffer_free(data.batch); + drm_intel_bufmgr_destroy(data.bufmgr); + close(data.drm_fd); + } +} diff --git a/tests/gem_ring_sync_loop.c b/tests/gem_ring_sync_loop.c index b689bcde..d4e7e2a8 100644 --- a/tests/gem_ring_sync_loop.c +++ b/tests/gem_ring_sync_loop.c @@ -28,19 +28,19 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" #include "i830_reg.h" +#include "intel_chipset.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; @@ -56,14 +56,15 @@ static drm_intel_bo *target_buffer; #define MI_DO_COMPARE (1<<21) static void -store_dword_loop(void) +store_dword_loop(int fd) { int i; + int num_rings = gem_get_num_rings(fd); srandom(0xdeadbeef); - for (i = 0; i < 0x100000; i++) { - int ring = random() % 3 + 1; + for (i = 0; i < SLOW_QUICK(0x100000, 10); i++) { + int ring = random() % num_rings + 1; if (ring == I915_EXEC_RENDER) { BEGIN_BATCH(4); @@ -90,50 +91,31 @@ store_dword_loop(void) drm_intel_bo_unmap(target_buffer); } -int main(int argc, char **argv) +igt_simple_main { int fd; int devid; - if (argc != 1) { - fprintf(stderr, "usage: %s\n", argv[0]); - exit(-1); - } - fd = drm_open_any(); devid = intel_get_drm_devid(fd); - if (!HAS_BLT_RING(devid)) { - fprintf(stderr, "inter ring check needs gen6+\n"); - return 77; - } + gem_require_ring(fd, I915_EXEC_BLT); bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - if (!bufmgr) { - fprintf(stderr, "failed to init libdrm\n"); - exit(-1); - } + igt_assert(bufmgr); drm_intel_bufmgr_gem_enable_reuse(bufmgr); batch = intel_batchbuffer_alloc(bufmgr, devid); - if (!batch) { - fprintf(stderr, "failed to create batch buffer\n"); - exit(-1); - } + igt_assert(batch); target_buffer = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096); - if (!target_buffer) { - fprintf(stderr, "failed to alloc target buffer\n"); - exit(-1); - } + igt_assert(target_buffer); - store_dword_loop(); + store_dword_loop(fd); drm_intel_bo_unreference(target_buffer); intel_batchbuffer_free(batch); drm_intel_bufmgr_destroy(bufmgr); close(fd); - - return 0; } diff --git a/tests/gem_ringfill.c b/tests/gem_ringfill.c index 5bae8f11..5700a74d 100644 --- a/tests/gem_ringfill.c +++ b/tests/gem_ringfill.c @@ -35,19 +35,19 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> -#include "drm.h" -#include "i915_drm.h" -#include "intel_bufmgr.h" -#include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" -#include "rendercopy.h" +#include <drm.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_chipset.h" +#include "intel_io.h" +#include "igt_aux.h" struct bo { const char *ring; @@ -95,8 +95,8 @@ static int check_bo(struct bo *b) int x = i % width; int y = i / width; - printf("%s: copy #%d at %d,%d failed: read 0x%08x\n", - b->ring, i, x, y, map[i]); + igt_info("%s: copy #%d at %d,%d failed: read 0x%08x\n", + b->ring, i, x, y, map[i]); } } drm_intel_bo_unmap(b->dst); @@ -114,9 +114,9 @@ static void destroy_bo(struct bo *b) static int check_ring(drm_intel_bufmgr *bufmgr, struct intel_batchbuffer *batch, const char *ring, - render_copyfunc_t copy) + igt_render_copyfunc_t copy) { - struct scratch_buf src, tmp, dst; + struct igt_buf src, tmp, dst; struct bo bo; char output[100]; int i; @@ -127,7 +127,6 @@ static int check_ring(drm_intel_bufmgr *bufmgr, src.stride = 4 * width; src.tiling = 0; - src.data = src.cpu_mapping = NULL; src.size = 4 * width * height; src.num_tiles = 4 * width * height; dst = tmp = src; @@ -155,18 +154,18 @@ static int check_ring(drm_intel_bufmgr *bufmgr, int x = i % width; int y = i / width; - drmtest_progress(output, i, width*height); + igt_progress(output, i, width*height); - assert(y < height); + igt_assert(y < height); /* Dummy load to fill the ring */ - copy(batch, &src, 0, 0, width, height, &tmp, 0, 0); + copy(batch, NULL, &src, 0, 0, width, height, &tmp, 0, 0); /* And copy the src into dst, pixel by pixel */ - copy(batch, &src, x, y, 1, 1, &dst, x, y); + copy(batch, NULL, &src, x, y, 1, 1, &dst, x, y); } /* verify */ - printf("verifying\n"); + igt_info("verifying\n"); i = check_bo(&bo); destroy_bo(&bo); @@ -174,60 +173,63 @@ static int check_ring(drm_intel_bufmgr *bufmgr, } static void blt_copy(struct intel_batchbuffer *batch, - struct scratch_buf *src, unsigned src_x, unsigned src_y, + drm_intel_context *context, + struct igt_buf *src, unsigned src_x, unsigned src_y, unsigned w, unsigned h, - struct scratch_buf *dst, unsigned dst_x, unsigned dst_y) + struct igt_buf *dst, unsigned dst_x, unsigned dst_y) { - BEGIN_BATCH(8); - OUT_BATCH(XY_SRC_COPY_BLT_CMD | - XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); + BLIT_COPY_BATCH_START(batch->devid, 0); OUT_BATCH((3 << 24) | /* 32 bits */ (0xcc << 16) | /* copy ROP */ dst->stride); OUT_BATCH((dst_y << 16) | dst_x); /* dst x1,y1 */ OUT_BATCH(((dst_y + h) << 16) | (dst_x + w)); /* dst x2,y2 */ OUT_RELOC(dst->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(batch->devid); OUT_BATCH((src_y << 16) | src_x); /* src x1,y1 */ OUT_BATCH(src->stride); OUT_RELOC(src->bo, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(batch->devid); ADVANCE_BATCH(); intel_batchbuffer_flush(batch); } -int main(int argc, char **argv) +drm_intel_bufmgr *bufmgr; +struct intel_batchbuffer *batch; +int fd; + +igt_main { - drm_intel_bufmgr *bufmgr; - struct intel_batchbuffer *batch; - render_copyfunc_t copy; - int fd, fails = 0; + igt_skip_on_simulation(); - fd = drm_open_any(); + igt_fixture { + fd = drm_open_any(); - bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - drm_intel_bufmgr_gem_enable_reuse(bufmgr); - batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + drm_intel_bufmgr_gem_enable_reuse(bufmgr); + batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); + } - fails += check_ring(bufmgr, batch, "blt", blt_copy); + igt_subtest("blitter") + check_ring(bufmgr, batch, "blt", blt_copy); /* Strictly only required on architectures with a separate BLT ring, * but lets stress everybody. */ - copy = NULL; - if (IS_GEN2(batch->devid)) - copy = gen2_render_copyfunc; - else if (IS_GEN3(batch->devid)) - copy = gen3_render_copyfunc; - else if (IS_GEN6(batch->devid)) - copy = gen6_render_copyfunc; - if (copy) - fails += check_ring(bufmgr, batch, "render", copy); - - intel_batchbuffer_free(batch); - drm_intel_bufmgr_destroy(bufmgr); - - close(fd); - - return fails != 0; + igt_subtest("render") { + igt_render_copyfunc_t copy; + + copy = igt_get_render_copyfunc(batch->devid); + igt_require(copy); + + check_ring(bufmgr, batch, "render", copy); + } + + igt_fixture { + intel_batchbuffer_free(batch); + drm_intel_bufmgr_destroy(bufmgr); + + close(fd); + } } diff --git a/tests/gem_seqno_wrap.c b/tests/gem_seqno_wrap.c new file mode 100644 index 00000000..fa38f1f2 --- /dev/null +++ b/tests/gem_seqno_wrap.c @@ -0,0 +1,645 @@ +/* + * Copyright (c) 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Mika Kuoppala <mika.kuoppala@intel.com> + * + */ + +/* + * This test runs blitcopy -> rendercopy with multiple buffers over wrap + * boundary. + */ + +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <limits.h> +#include <wordexp.h> +#include <getopt.h> +#include <signal.h> +#include <errno.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "igt_core.h" +#include "igt_aux.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_io.h" +#include "intel_chipset.h" + +static int devid; +static int card_index = 0; +static uint32_t last_seqno = 0; + +static struct intel_batchbuffer *batch_blt; +static struct intel_batchbuffer *batch_3d; + +struct option_struct { + int rounds; + int background; + char cmd[1024]; + int timeout; + int dontwrap; + int prewrap_space; + int random; + int buffers; +}; + +static struct option_struct options; + +static void init_buffer(drm_intel_bufmgr *bufmgr, + struct igt_buf *buf, + drm_intel_bo *bo, + int width, int height) +{ + /* buf->bo = drm_intel_bo_alloc(bufmgr, "", size, 4096); */ + buf->bo = bo; + buf->size = width * height * 4; + igt_assert(buf->bo); + buf->tiling = I915_TILING_NONE; + buf->num_tiles = width * height * 4; + buf->stride = width * 4; +} + +static void +set_bo(drm_intel_bo *bo, uint32_t val, int width, int height) +{ + int size = width * height; + uint32_t *vaddr; + + drm_intel_gem_bo_start_gtt_access(bo, true); + vaddr = bo->virtual; + while (size--) + *vaddr++ = val; +} + +static void +cmp_bo(drm_intel_bo *bo, uint32_t val, int width, int height) +{ + int size = width * height; + uint32_t *vaddr; + + drm_intel_gem_bo_start_gtt_access(bo, false); + vaddr = bo->virtual; + while (size--) { + igt_assert_f(*vaddr++ == val, + "%d: 0x%x differs from assumed 0x%x\n" + "seqno_before_test 0x%x, " + " approximated seqno on test fail 0x%x\n", + width * height - size, *vaddr-1, val, + last_seqno, last_seqno + val * 2); + } +} + +static drm_intel_bo * +create_bo(drm_intel_bufmgr *bufmgr, uint32_t val, int width, int height) +{ + drm_intel_bo *bo; + + bo = drm_intel_bo_alloc(bufmgr, "bo", width * height * 4, 0); + igt_assert(bo); + + /* gtt map doesn't have a write parameter, so just keep the mapping + * around (to avoid the set_domain with the gtt write domain set) and + * manually tell the kernel when we start access the gtt. */ + drm_intel_gem_bo_map_gtt(bo); + + set_bo(bo, val, width, height); + + return bo; +} + +static void release_bo(drm_intel_bo *bo) +{ + drm_intel_gem_bo_unmap_gtt(bo); + drm_intel_bo_unreference(bo); +} + +static void render_copyfunc(struct igt_buf *src, + struct igt_buf *dst, + int width, + int height) +{ + const int src_x = 0, src_y = 0, dst_x = 0, dst_y = 0; + igt_render_copyfunc_t rendercopy = igt_get_render_copyfunc(devid); + static int warned = 0; + + if (rendercopy) { + rendercopy(batch_3d, NULL, + src, src_x, src_y, + width, height, + dst, dst_x, dst_y); + intel_batchbuffer_flush(batch_3d); + } else { + if (!warned) { + printf("No render copy found for this gen, " + "test is shallow!\n"); + warned = 1; + } + igt_assert(dst->bo); + igt_assert(src->bo); + intel_copy_bo(batch_blt, dst->bo, src->bo, width*height*4); + intel_batchbuffer_flush(batch_blt); + } +} + +static void exchange_uint(void *array, unsigned i, unsigned j) +{ + unsigned *i_arr = array; + unsigned i_tmp; + + i_tmp = i_arr[i]; + i_arr[i] = i_arr[j]; + i_arr[j] = i_tmp; +} + +static void run_sync_test(int num_buffers, bool verify) +{ + drm_intel_bufmgr *bufmgr; + int max; + drm_intel_bo **src, **dst1, **dst2; + int width = 128, height = 128; + int fd; + int i; + unsigned int *p_dst1, *p_dst2; + struct igt_buf *s_src, *s_dst; + + fd = drm_open_any(); + igt_assert(fd >= 0); + + gem_quiescent_gpu(fd); + + devid = intel_get_drm_devid(fd); + + max = gem_aperture_size (fd) / (1024 * 1024) / 2; + if (num_buffers > max) + num_buffers = max; + + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + drm_intel_bufmgr_gem_enable_reuse(bufmgr); + batch_blt = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); + igt_assert(batch_blt); + batch_3d = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); + igt_assert(batch_3d); + + src = malloc(num_buffers * sizeof(*src)); + igt_assert(src); + + dst1 = malloc(num_buffers * sizeof(*dst1)); + igt_assert(dst1); + + dst2 = malloc(num_buffers * sizeof(*dst2)); + igt_assert(dst2); + + s_src = malloc(num_buffers * sizeof(*s_src)); + igt_assert(s_src); + + s_dst = malloc(num_buffers * sizeof(*s_dst)); + igt_assert(s_dst); + + p_dst1 = malloc(num_buffers * sizeof(unsigned int)); + igt_assert(p_dst1); + + p_dst2 = malloc(num_buffers * sizeof(unsigned int)); + igt_assert(p_dst2); + + for (i = 0; i < num_buffers; i++) { + p_dst1[i] = p_dst2[i] = i; + src[i] = create_bo(bufmgr, i, width, height); + igt_assert(src[i]); + dst1[i] = create_bo(bufmgr, ~i, width, height); + igt_assert(dst1[i]); + dst2[i] = create_bo(bufmgr, ~i, width, height); + igt_assert(dst2[i]); + init_buffer(bufmgr, &s_src[i], src[i], width, height); + init_buffer(bufmgr, &s_dst[i], dst1[i], width, height); + } + + igt_permute_array(p_dst1, num_buffers, exchange_uint); + igt_permute_array(p_dst2, num_buffers, exchange_uint); + + for (i = 0; i < num_buffers; i++) + render_copyfunc(&s_src[i], &s_dst[p_dst1[i]], width, height); + + /* Only sync between buffers if this is actual test run and + * not a seqno filler */ + if (verify) { + for (i = 0; i < num_buffers; i++) + intel_copy_bo(batch_blt, dst2[p_dst2[i]], dst1[p_dst1[i]], + width*height*4); + + for (i = 0; i < num_buffers; i++) { + cmp_bo(dst2[p_dst2[i]], i, width, height); + } + } + + for (i = 0; i < num_buffers; i++) { + release_bo(src[i]); + release_bo(dst1[i]); + release_bo(dst2[i]); + } + + intel_batchbuffer_free(batch_3d); + intel_batchbuffer_free(batch_blt); + drm_intel_bufmgr_destroy(bufmgr); + + free(p_dst1); + free(p_dst2); + free(s_dst); + free(s_src); + free(dst2); + free(dst1); + free(src); + + gem_quiescent_gpu(fd); + + close(fd); +} + +static int run_cmd(char *s) +{ + int pid; + int r = -1; + int status = 0; + wordexp_t wexp; + int i; + r = wordexp(s, &wexp, 0); + if (r != 0) { + printf("can't parse %s\n", s); + return r; + } + + for(i = 0; i < wexp.we_wordc; i++) + printf("argv[%d] = %s\n", i, wexp.we_wordv[i]); + + pid = fork(); + + if (pid == 0) { + char path[PATH_MAX]; + char full_path[PATH_MAX]; + + if (getcwd(path, PATH_MAX) == NULL) + perror("getcwd"); + + igt_assert(snprintf(full_path, PATH_MAX, "%s/%s", path, wexp.we_wordv[0]) > 0); + + r = execv(full_path, wexp.we_wordv); + if (r == -1) + perror("execv failed"); + } else { + int waitcount = options.timeout; + + while(waitcount-- > 0) { + r = waitpid(pid, &status, WNOHANG); + if (r == pid) { + if(WIFEXITED(status)) { + if (WEXITSTATUS(status)) + fprintf(stderr, + "child returned with %d\n", + WEXITSTATUS(status)); + return WEXITSTATUS(status); + } + } else if (r != 0) { + perror("waitpid"); + return -errno; + } + + sleep(3); + } + + kill(pid, SIGKILL); + return -ETIMEDOUT; + } + + return r; +} + +static const char *dfs_base = "/sys/kernel/debug/dri"; +static const char *dfs_entry = "i915_next_seqno"; + +static int dfs_open(int mode) +{ + char fname[FILENAME_MAX]; + int fh; + + snprintf(fname, FILENAME_MAX, "%s/%i/%s", + dfs_base, card_index, dfs_entry); + + fh = open(fname, mode); + igt_require(fh >= 0); + + return fh; +} + +static int __read_seqno(uint32_t *seqno) +{ + int fh; + char buf[32]; + int r; + char *p; + unsigned long int tmp; + + fh = dfs_open(O_RDONLY); + + r = read(fh, buf, sizeof(buf) - 1); + close(fh); + if (r < 0) { + perror("read"); + return -errno; + } + + buf[r] = 0; + + p = strstr(buf, "0x"); + if (!p) + p = buf; + + errno = 0; + tmp = strtoul(p, NULL, 0); + if (tmp == ULONG_MAX && errno) { + perror("strtoul"); + return -errno; + } + + *seqno = tmp; + + igt_debug("next_seqno: 0x%x\n", *seqno); + + return 0; +} + +static int read_seqno(void) +{ + uint32_t seqno = 0; + int r; + int wrap = 0; + + r = __read_seqno(&seqno); + igt_assert(r == 0); + + if (last_seqno > seqno) + wrap++; + + last_seqno = seqno; + + return wrap; +} + +static int write_seqno(uint32_t seqno) +{ + int fh; + char buf[32]; + int r; + uint32_t rb; + + if (options.dontwrap) + return 0; + + fh = dfs_open(O_RDWR); + igt_assert(snprintf(buf, sizeof(buf), "0x%x", seqno) > 0); + + r = write(fh, buf, strnlen(buf, sizeof(buf))); + close(fh); + if (r < 0) + return r; + + igt_assert(r == strnlen(buf, sizeof(buf))); + + last_seqno = seqno; + + igt_debug("next_seqno set to: 0x%x\n", seqno); + + r = __read_seqno(&rb); + if (r < 0) + return r; + + if (rb != seqno) { + printf("seqno readback differs rb:0x%x vs w:0x%x\n", rb, seqno); + return -1; + } + + return 0; +} + +static uint32_t calc_prewrap_val(void) +{ + const int pval = options.prewrap_space; + + if (options.random == 0) + return pval; + + if (pval == 0) + return 0; + + return (random() % pval); +} + +static void run_test(void) +{ + if (strnlen(options.cmd, sizeof(options.cmd)) > 0) + igt_assert(run_cmd(options.cmd) == 0); + else + run_sync_test(options.buffers, true); +} + +static void preset_run_once(void) +{ + igt_assert(write_seqno(1) == 0); + run_test(); + + igt_assert(write_seqno(0x7fffffff) == 0); + run_test(); + + igt_assert(write_seqno(0xffffffff) == 0); + run_test(); + + igt_assert(write_seqno(0xfffffff0) == 0); + run_test(); +} + +static void random_run_once(void) +{ + uint32_t val; + + do { + val = random() % UINT32_MAX; + if (RAND_MAX < UINT32_MAX) + val += random(); + } while (val == 0); + + igt_assert(write_seqno(val) == 0); + run_test(); +} + +static void wrap_run_once(void) +{ + const uint32_t pw_val = calc_prewrap_val(); + + igt_assert(write_seqno(UINT32_MAX - pw_val) == 0); + + while(!read_seqno()) + run_test(); +} + +static void background_run_once(void) +{ + const uint32_t pw_val = calc_prewrap_val(); + + igt_assert(write_seqno(UINT32_MAX - pw_val) == 0); + + while(!read_seqno()) + sleep(3); +} + +static void print_usage(const char *s) +{ + printf("%s: [OPTION]...\n", s); + printf(" where options are:\n"); + printf(" -b --background run in background inducing wraps\n"); + printf(" -c --cmd=cmdstring use cmdstring to cross wrap\n"); + printf(" -n --rounds=num run num times across wrap boundary, 0 == forever\n"); + printf(" -t --timeout=sec set timeout to wait for testrun to sec seconds\n"); + printf(" -d --dontwrap don't wrap just run the test\n"); + printf(" -p --prewrap=n set seqno to WRAP - n for each testrun\n"); + printf(" -r --norandom dont randomize prewrap space\n"); + printf(" -i --buffers number of buffers to copy\n"); + igt_fail(-1); +} + +static void parse_options(int argc, char **argv) +{ + int c; + int option_index = 0; + static struct option long_options[] = { + {"cmd", required_argument, 0, 'c'}, + {"rounds", required_argument, 0, 'n'}, + {"background", no_argument, 0, 'b'}, + {"timeout", required_argument, 0, 't'}, + {"dontwrap", no_argument, 0, 'd'}, + {"prewrap", required_argument, 0, 'p'}, + {"norandom", no_argument, 0, 'r'}, + {"buffers", required_argument, 0, 'i'}, + }; + + strcpy(options.cmd, ""); + options.rounds = SLOW_QUICK(50, 2); + options.background = 0; + options.dontwrap = 0; + options.timeout = 20; + options.random = 1; + options.prewrap_space = 21; + options.buffers = 10; + + while((c = getopt_long(argc, argv, "c:n:bvt:dp:ri:", + long_options, &option_index)) != -1) { + switch(c) { + case 'b': + options.background = 1; + printf("running in background inducing wraps\n"); + break; + case 'd': + options.dontwrap = 1; + printf("won't wrap after testruns\n"); + break; + case 'n': + options.rounds = atoi(optarg); + printf("running %d rounds\n", options.rounds); + break; + case 'c': + strncpy(options.cmd, optarg, sizeof(options.cmd) - 1); + options.cmd[sizeof(options.cmd) - 1] = 0; + printf("cmd set to %s\n", options.cmd); + break; + case 'i': + options.buffers = atoi(optarg); + printf("buffers %d\n", options.buffers); + break; + case 't': + options.timeout = atoi(optarg); + if (options.timeout == 0) + options.timeout = 10; + printf("setting timeout to %d seconds\n", + options.timeout); + break; + case 'r': + options.random = 0; + break; + case 'p': + options.prewrap_space = atoi(optarg); + printf("prewrap set to %d (0x%x)\n", + options.prewrap_space, UINT32_MAX - + options.prewrap_space); + break; + default: + printf("unkown command options\n"); + print_usage(argv[0]); + break; + } + } + + if (optind < argc) { + printf("unkown command options\n"); + print_usage(argv[0]); + } +} + +int main(int argc, char **argv) +{ + int wcount = 0; + int r = -1; + + igt_simple_init(); + + parse_options(argc, argv); + + card_index = drm_get_card(); + + srandom(time(NULL)); + + while(options.rounds == 0 || wcount < options.rounds) { + if (options.background) { + background_run_once(); + } else { + preset_run_once(); + random_run_once(); + wrap_run_once(); + } + + wcount++; + + igt_debug("%s done: %d\n", + options.dontwrap ? "tests" : "wraps", wcount); + } + + if (options.rounds == wcount) { + igt_debug("done %d wraps successfully\n", wcount); + return 0; + } + + return r; +} diff --git a/tests/gem_set_tiling_vs_blt.c b/tests/gem_set_tiling_vs_blt.c index 5fa90d49..d9751552 100644 --- a/tests/gem_set_tiling_vs_blt.c +++ b/tests/gem_set_tiling_vs_blt.c @@ -47,7 +47,6 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> @@ -55,11 +54,12 @@ #include <sys/time.h> #include <stdbool.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_chipset.h" +#include "intel_io.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; @@ -82,23 +82,22 @@ static void do_test(uint32_t tiling, unsigned stride, uint32_t blt_stride, blt_bits; bool tiling_changed = false; - printf("filling ring .. "); + igt_info("filling ring .. "); busy_bo = drm_intel_bo_alloc(bufmgr, "busy bo bo", 16*1024*1024, 4096); for (i = 0; i < 250; i++) { - BEGIN_BATCH(8); - OUT_BATCH(XY_SRC_COPY_BLT_CMD | - XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); + BLIT_COPY_BATCH_START(devid, 0); OUT_BATCH((3 << 24) | /* 32 bits */ (0xcc << 16) | /* copy ROP */ 2*1024*4); OUT_BATCH(0 << 16 | 1024); OUT_BATCH((2048) << 16 | (2048)); OUT_RELOC_FENCED(busy_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(devid); OUT_BATCH(0 << 16 | 0); OUT_BATCH(2*1024*4); OUT_RELOC_FENCED(busy_bo, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(devid); ADVANCE_BATCH(); if (IS_GEN6(devid) || IS_GEN7(devid)) { @@ -111,7 +110,7 @@ static void do_test(uint32_t tiling, unsigned stride, } intel_batchbuffer_flush(batch); - printf("playing tricks .. "); + igt_info("playing tricks .. "); /* first allocate the target so it gets out of the way of playing funky * tricks */ target_bo = drm_intel_bo_alloc(bufmgr, "target bo", TEST_SIZE, 4096); @@ -121,7 +120,7 @@ static void do_test(uint32_t tiling, unsigned stride, test_bo = drm_intel_bo_alloc(bufmgr, "tiled busy bo", TEST_SIZE, 4096); test_bo_handle = test_bo->handle; ret = drm_intel_bo_set_tiling(test_bo, &tiling_after, stride_after); - assert(ret == 0); + igt_assert(ret == 0); drm_intel_gem_bo_map_gtt(test_bo); ptr = test_bo->virtual; *ptr = 0; @@ -135,12 +134,13 @@ static void do_test(uint32_t tiling, unsigned stride, /* note we need a bo bigger than batches, otherwise the buffer reuse * trick will fail. */ test_bo = drm_intel_bo_alloc(bufmgr, "busy bo", TEST_SIZE, 4096); - if (test_bo_handle != test_bo->handle) - fprintf(stderr, "libdrm reuse trick failed\n"); + /* double check that the reuse trick worked */ + igt_assert(test_bo_handle == test_bo->handle); + test_bo_handle = test_bo->handle; /* ensure we have the right tiling before we start. */ ret = drm_intel_bo_set_tiling(test_bo, &tiling, stride); - assert(ret == 0); + igt_assert(ret == 0); if (tiling == I915_TILING_NONE) { drm_intel_bo_subdata(test_bo, 0, TEST_SIZE, data); @@ -159,58 +159,55 @@ static void do_test(uint32_t tiling, unsigned stride, blt_bits = XY_SRC_COPY_BLT_SRC_TILED; } - BEGIN_BATCH(8); - OUT_BATCH(XY_SRC_COPY_BLT_CMD | - XY_SRC_COPY_BLT_WRITE_ALPHA | - blt_bits | - XY_SRC_COPY_BLT_WRITE_RGB); + BLIT_COPY_BATCH_START(devid, blt_bits); OUT_BATCH((3 << 24) | /* 32 bits */ (0xcc << 16) | /* copy ROP */ stride); OUT_BATCH(0 << 16 | 0); OUT_BATCH((TEST_HEIGHT(stride)) << 16 | (TEST_WIDTH(stride))); OUT_RELOC_FENCED(target_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(devid); OUT_BATCH(0 << 16 | 0); OUT_BATCH(blt_stride); OUT_RELOC_FENCED(test_bo, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(devid); ADVANCE_BATCH(); intel_batchbuffer_flush(batch); drm_intel_bo_unreference(test_bo); test_bo = drm_intel_bo_alloc_for_render(bufmgr, "tiled busy bo", TEST_SIZE, 4096); - if (test_bo_handle != test_bo->handle) - fprintf(stderr, "libdrm reuse trick failed\n"); + /* double check that the reuse trick worked */ + igt_assert(test_bo_handle == test_bo->handle); ret = drm_intel_bo_set_tiling(test_bo, &tiling_after, stride_after); - assert(ret == 0); + igt_assert(ret == 0); /* Note: We don't care about gen4+ here because the blitter doesn't use * fences there. So not setting tiling flags on the tiled buffer is ok. */ - BEGIN_BATCH(8); - OUT_BATCH(XY_SRC_COPY_BLT_CMD | - XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); + BLIT_COPY_BATCH_START(devid, 0); OUT_BATCH((3 << 24) | /* 32 bits */ (0xcc << 16) | /* copy ROP */ stride_after); OUT_BATCH(0 << 16 | 0); OUT_BATCH((1) << 16 | (1)); OUT_RELOC_FENCED(test_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(devid); OUT_BATCH(0 << 16 | 0); OUT_BATCH(stride_after); OUT_RELOC_FENCED(test_bo, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(devid); ADVANCE_BATCH(); intel_batchbuffer_flush(batch); /* Now try to trick the kernel the kernel into changing up the fencing * too early. */ - printf("checking .. "); + igt_info("checking .. "); memset(data, 0, TEST_SIZE); drm_intel_bo_get_subdata(target_bo, 0, TEST_SIZE, data); for (i = 0; i < TEST_SIZE/4; i++) - assert(data[i] == i); + igt_assert(data[i] == i); /* check whether tiling on the test_bo actually changed. */ drm_intel_gem_bo_map_gtt(test_bo); @@ -220,50 +217,56 @@ static void do_test(uint32_t tiling, unsigned stride, tiling_changed = true; ptr = NULL; drm_intel_gem_bo_unmap_gtt(test_bo); - assert(tiling_changed); + igt_assert(tiling_changed); drm_intel_bo_unreference(test_bo); drm_intel_bo_unreference(target_bo); drm_intel_bo_unreference(busy_bo); - printf("done\n"); + igt_info("done\n"); } -int main(int argc, char **argv) +int fd; + +igt_main { - int i, fd; + int i; uint32_t tiling, tiling_after; - for (i = 0; i < 1024*256; i++) - data[i] = i; + igt_skip_on_simulation(); - fd = drm_open_any(); + igt_fixture { + for (i = 0; i < 1024*256; i++) + data[i] = i; - bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - drm_intel_bufmgr_gem_enable_reuse(bufmgr); - devid = intel_get_drm_devid(fd); - batch = intel_batchbuffer_alloc(bufmgr, devid); + fd = drm_open_any(); + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + drm_intel_bufmgr_gem_enable_reuse(bufmgr); + devid = intel_get_drm_devid(fd); + batch = intel_batchbuffer_alloc(bufmgr, devid); + } - printf("testing untiled->tiled transisition:\n"); - tiling = I915_TILING_NONE; - tiling_after = I915_TILING_X; - do_test(tiling, TEST_STRIDE, tiling_after, TEST_STRIDE); - assert(tiling == I915_TILING_NONE); - assert(tiling_after == I915_TILING_X); - - printf("testing tiled->untiled transisition:\n"); - tiling = I915_TILING_X; - tiling_after = I915_TILING_NONE; - do_test(tiling, TEST_STRIDE, tiling_after, TEST_STRIDE); - assert(tiling == I915_TILING_X); - assert(tiling_after == I915_TILING_NONE); + igt_subtest("untiled-to-tiled") { + tiling = I915_TILING_NONE; + tiling_after = I915_TILING_X; + do_test(tiling, TEST_STRIDE, tiling_after, TEST_STRIDE); + igt_assert(tiling == I915_TILING_NONE); + igt_assert(tiling_after == I915_TILING_X); + } - printf("testing tiled->tiled transisition:\n"); - tiling = I915_TILING_X; - tiling_after = I915_TILING_X; - do_test(tiling, TEST_STRIDE/2, tiling_after, TEST_STRIDE); - assert(tiling == I915_TILING_X); - assert(tiling_after == I915_TILING_X); + igt_subtest("tiled-to-untiled") { + tiling = I915_TILING_X; + tiling_after = I915_TILING_NONE; + do_test(tiling, TEST_STRIDE, tiling_after, TEST_STRIDE); + igt_assert(tiling == I915_TILING_X); + igt_assert(tiling_after == I915_TILING_NONE); + } - return 0; + igt_subtest("tiled-to-tiled") { + tiling = I915_TILING_X; + tiling_after = I915_TILING_X; + do_test(tiling, TEST_STRIDE/2, tiling_after, TEST_STRIDE); + igt_assert(tiling == I915_TILING_X); + igt_assert(tiling_after == I915_TILING_X); + } } diff --git a/tests/gem_set_tiling_vs_gtt.c b/tests/gem_set_tiling_vs_gtt.c index 1241b54d..e0ef2b7b 100644 --- a/tests/gem_set_tiling_vs_gtt.c +++ b/tests/gem_set_tiling_vs_gtt.c @@ -29,17 +29,16 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/ioctl.h> -#include <sys/mman.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "intel_chipset.h" #define OBJECT_SIZE (1024*1024) #define TEST_STRIDE (1024*4) @@ -48,7 +47,7 @@ * Testcase: Check set_tiling vs gtt mmap coherency */ -int main(int argc, char **argv) +igt_simple_main { int fd; uint32_t *ptr; @@ -58,6 +57,8 @@ int main(int argc, char **argv) bool tiling_changed; int tile_height; + igt_skip_on_simulation(); + fd = drm_open_any(); if (IS_GEN2(intel_get_drm_devid(fd))) @@ -67,7 +68,7 @@ int main(int argc, char **argv) handle = gem_create(fd, OBJECT_SIZE); ptr = gem_mmap(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE); - assert(ptr); + igt_assert(ptr); /* gtt coherency is done with set_domain in libdrm, don't break that */ gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); @@ -76,7 +77,7 @@ int main(int argc, char **argv) gem_set_tiling(fd, handle, I915_TILING_X, TEST_STRIDE); - printf("testing untiled->tiled\n"); + igt_info("testing untiled->tiled\n"); tiling_changed = false; gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, 0); /* Too lazy to check for the correct tiling, and impossible anyway on @@ -84,7 +85,7 @@ int main(int argc, char **argv) for (i = 0; i < OBJECT_SIZE/4; i++) if (ptr[i] != data[i]) tiling_changed = true; - assert(tiling_changed); + igt_assert(tiling_changed); gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); for (i = 0; i < OBJECT_SIZE/4; i++) @@ -92,7 +93,7 @@ int main(int argc, char **argv) gem_set_tiling(fd, handle, I915_TILING_X, TEST_STRIDE*2); - printf("testing tiled->tiled\n"); + igt_info("testing tiled->tiled\n"); gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, 0); for (i = 0; i < OBJECT_SIZE/4; i++) { int tile_row = i / (TEST_STRIDE * tile_height / 4); @@ -104,13 +105,11 @@ int main(int argc, char **argv) + half*tile_height + ofs; uint32_t val = data[data_i]; - if (ptr[i] != val) { - printf("mismatch at %i, row=%i, half=%i, ofs=%i\n", - i, row, half, ofs); - printf("read: 0x%08x, expected: 0x%08x\n", - ptr[i], val); - assert(0); - } + igt_assert_f(ptr[i] == val, + "mismatch at %i, row=%i, half=%i, ofs=%i, " + "read: 0x%08x, expected: 0x%08x\n", + i, row, half, ofs, + ptr[i], val); } @@ -119,7 +118,7 @@ int main(int argc, char **argv) ptr[i] = data[i] = i; gem_set_tiling(fd, handle, I915_TILING_NONE, 0); - printf("testing tiled->untiled\n"); + igt_info("testing tiled->untiled\n"); tiling_changed = false; gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, 0); /* Too lazy to check for the correct tiling, and impossible anyway on @@ -127,11 +126,9 @@ int main(int argc, char **argv) for (i = 0; i < OBJECT_SIZE/4; i++) if (ptr[i] != data[i]) tiling_changed = true; - assert(tiling_changed); + igt_assert(tiling_changed); munmap(ptr, OBJECT_SIZE); close(fd); - - return 0; } diff --git a/tests/gem_set_tiling_vs_pwrite.c b/tests/gem_set_tiling_vs_pwrite.c index 35ec5cdc..cf5aaeb0 100644 --- a/tests/gem_set_tiling_vs_pwrite.c +++ b/tests/gem_set_tiling_vs_pwrite.c @@ -29,17 +29,15 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/ioctl.h> -#include <sys/mman.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" #define OBJECT_SIZE (1024*1024) #define TEST_STRIDE (1024*4) @@ -48,7 +46,7 @@ * Testcase: Check set_tiling vs pwrite coherency */ -int main(int argc, char **argv) +igt_simple_main { int fd; uint32_t *ptr; @@ -56,6 +54,8 @@ int main(int argc, char **argv) int i; uint32_t handle; + igt_skip_on_simulation(); + fd = drm_open_any(); for (i = 0; i < OBJECT_SIZE/4; i++) @@ -63,7 +63,7 @@ int main(int argc, char **argv) handle = gem_create(fd, OBJECT_SIZE); ptr = gem_mmap(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE); - assert(ptr); + igt_assert(ptr); gem_set_tiling(fd, handle, I915_TILING_X, TEST_STRIDE); @@ -71,12 +71,12 @@ int main(int argc, char **argv) gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); *ptr = 0xdeadbeef; - printf("testing pwrite on tiled buffer\n"); + igt_info("testing pwrite on tiled buffer\n"); gem_write(fd, handle, 0, data, OBJECT_SIZE); memset(data, 0, OBJECT_SIZE); gem_read(fd, handle, 0, data, OBJECT_SIZE); for (i = 0; i < OBJECT_SIZE/4; i++) - assert(i == data[i]); + igt_assert(i == data[i]); /* touch it before changing the tiling, so that the fence sticks around */ gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); @@ -84,16 +84,14 @@ int main(int argc, char **argv) gem_set_tiling(fd, handle, I915_TILING_NONE, 0); - printf("testing pwrite on untiled, but still fenced buffer\n"); + igt_info("testing pwrite on untiled, but still fenced buffer\n"); gem_write(fd, handle, 0, data, OBJECT_SIZE); memset(data, 0, OBJECT_SIZE); gem_read(fd, handle, 0, data, OBJECT_SIZE); for (i = 0; i < OBJECT_SIZE/4; i++) - assert(i == data[i]); + igt_assert(i == data[i]); munmap(ptr, OBJECT_SIZE); close(fd); - - return 0; } diff --git a/tests/gem_storedw_batches_loop.c b/tests/gem_storedw_batches_loop.c index 8cf5f719..fef3718f 100644 --- a/tests/gem_storedw_batches_loop.c +++ b/tests/gem_storedw_batches_loop.c @@ -29,145 +29,150 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" +#include "intel_chipset.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" static drm_intel_bufmgr *bufmgr; static drm_intel_bo *target_bo; static int has_ppgtt = 0; +#define SECURE_DISPATCH (1<<0) + /* Like the store dword test, but we create new command buffers each time */ static void -store_dword_loop(void) +store_dword_loop(int divider, unsigned flags) { - int cmd, i, val = 0, ret; + int cmd, i, val = 0; uint32_t *buf; drm_intel_bo *cmd_bo; + igt_info("running storedw loop with stall every %i batch\n", divider); + cmd = MI_STORE_DWORD_IMM; if (!has_ppgtt) cmd |= MI_MEM_VIRTUAL; - for (i = 0; i < 0x80000; i++) { + for (i = 0; i < SLOW_QUICK(0x2000, 4); i++) { + int j = 0; + int cmd_address_offset; cmd_bo = drm_intel_bo_alloc(bufmgr, "cmd bo", 4096, 4096); - if (!cmd_bo) { - fprintf(stderr, "failed to alloc cmd bo\n"); - exit(-1); - } + igt_assert(cmd_bo); + /* Upload through cpu mmaps to make sure we don't have a gtt + * mapping which could paper over secure batch submission + * failing to bind that. */ drm_intel_bo_map(cmd_bo, 1); buf = cmd_bo->virtual; - buf[0] = cmd; - buf[1] = 0; - buf[2] = target_bo->offset; - buf[3] = 0x42000000 + val; - - ret = drm_intel_bo_references(cmd_bo, target_bo); - if (ret) { - fprintf(stderr, "failed to link cmd & target bos\n"); - exit(-1); + buf[j++] = cmd; + if (intel_gen(drm_intel_bufmgr_gem_get_devid(bufmgr)) >= 8) { + cmd_address_offset = j * 4; + buf[j++] = target_bo->offset; + buf[j++] = 0; + } else { + buf[j++] = 0; + cmd_address_offset = j * 4; + buf[j++] = target_bo->offset; } + igt_assert(j > 0); + buf[j++] = 0x42000000 + val; - ret = drm_intel_bo_emit_reloc(cmd_bo, 8, target_bo, 0, - I915_GEM_DOMAIN_INSTRUCTION, - I915_GEM_DOMAIN_INSTRUCTION); - if (ret) { - fprintf(stderr, "failed to emit reloc\n"); - exit(-1); - } + igt_assert(drm_intel_bo_references(cmd_bo, target_bo) == 0); - buf[4] = MI_BATCH_BUFFER_END; - buf[5] = MI_BATCH_BUFFER_END; + igt_assert(drm_intel_bo_emit_reloc(cmd_bo, cmd_address_offset, target_bo, 0, + I915_GEM_DOMAIN_INSTRUCTION, + I915_GEM_DOMAIN_INSTRUCTION) == 0); + buf[j++] = MI_BATCH_BUFFER_END; + buf[j++] = MI_BATCH_BUFFER_END; drm_intel_bo_unmap(cmd_bo); - ret = drm_intel_bo_references(cmd_bo, target_bo); - if (ret != 1) { - fprintf(stderr, "bad bo reference count: %d\n", ret); - exit(-1); - } + igt_assert(drm_intel_bo_references(cmd_bo, target_bo) == 1); - ret = drm_intel_bo_exec(cmd_bo, 6 * 4, NULL, 0, 0); - if (ret) { - fprintf(stderr, "bo exec failed: %d\n", ret); - exit(-1); - } +#define LOCAL_I915_EXEC_SECURE (1<<9) + igt_assert(drm_intel_bo_mrb_exec(cmd_bo, j * 4, NULL, 0, 0, + I915_EXEC_BLT | + (flags & SECURE_DISPATCH ? LOCAL_I915_EXEC_SECURE : 0)) + == 0); + + if (i % divider != 0) + goto cont; drm_intel_bo_wait_rendering(cmd_bo); drm_intel_bo_map(target_bo, 1); buf = target_bo->virtual; - if (buf[0] != (0x42000000 | val)) { - fprintf(stderr, - "value mismatch: cur 0x%08x, stored 0x%08x\n", - buf[0], 0x42000000 | val); - exit(-1); - } + igt_assert_f(buf[0] == (0x42000000 | val), + "value mismatch: cur 0x%08x, stored 0x%08x\n", + buf[0], 0x42000000 | val); + buf[0] = 0; /* let batch write it again */ drm_intel_bo_unmap(target_bo); +cont: drm_intel_bo_unreference(cmd_bo); val++; } - printf("completed %d writes successfully\n", i); + igt_info("completed %d writes successfully\n", i); } -int main(int argc, char **argv) +int fd; +int devid; + +igt_main { - int fd; - int devid; + igt_skip_on_simulation(); - if (argc != 1) { - fprintf(stderr, "usage: %s\n", argv[0]); - exit(-1); - } + igt_fixture { + fd = drm_open_any(); + devid = intel_get_drm_devid(fd); - fd = drm_open_any(); - devid = intel_get_drm_devid(fd); + has_ppgtt = gem_uses_aliasing_ppgtt(fd); - has_ppgtt = gem_uses_aliasing_ppgtt(fd); + /* storedw needs gtt address on gen4+/g33 and snoopable memory. + * Strictly speaking we could implement this now ... */ + igt_require(intel_gen(devid) >= 6); - if (IS_GEN2(devid) || IS_GEN3(devid) || IS_GEN4(devid) || IS_GEN5(devid)) { + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + igt_assert(bufmgr); - fprintf(stderr, "MI_STORE_DATA can only use GTT address on gen4+/g33 and" - "needs snoopable mem on pre-gen6\n"); - return 77; - } + // drm_intel_bufmgr_gem_enable_reuse(bufmgr); - - bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - if (!bufmgr) { - fprintf(stderr, "failed to init libdrm\n"); - exit(-1); + target_bo = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096); + igt_assert(target_bo); } -// drm_intel_bufmgr_gem_enable_reuse(bufmgr); - target_bo = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096); - if (!target_bo) { - fprintf(stderr, "failed to alloc target buffer\n"); - exit(-1); + igt_subtest("normal") { + store_dword_loop(1, 0); + store_dword_loop(2, 0); + store_dword_loop(3, 0); + store_dword_loop(5, 0); } - store_dword_loop(); - - drm_intel_bo_unreference(target_bo); - drm_intel_bufmgr_destroy(bufmgr); + igt_subtest("secure-dispatch") { + store_dword_loop(1, SECURE_DISPATCH); + store_dword_loop(2, SECURE_DISPATCH); + store_dword_loop(3, SECURE_DISPATCH); + store_dword_loop(5, SECURE_DISPATCH); + } - close(fd); + igt_fixture { + drm_intel_bo_unreference(target_bo); + drm_intel_bufmgr_destroy(bufmgr); - return 0; + close(fd); + } } diff --git a/tests/gem_storedw_loop_blt.c b/tests/gem_storedw_loop_blt.c index dda9b835..8c4157d5 100644 --- a/tests/gem_storedw_loop_blt.c +++ b/tests/gem_storedw_loop_blt.c @@ -29,18 +29,18 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "intel_chipset.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; @@ -52,103 +52,105 @@ static int has_ppgtt = 0; */ static void -store_dword_loop(void) +emit_store_dword_imm(int devid, drm_intel_bo *dest, uint32_t val) { - int cmd, i, val = 0; - uint32_t *buf; - + int cmd; cmd = MI_STORE_DWORD_IMM; if (!has_ppgtt) cmd |= MI_MEM_VIRTUAL; - for (i = 0; i < 0x100000; i++) { + if (intel_gen(devid) >= 8) { + BEGIN_BATCH(4); + OUT_BATCH(cmd); + OUT_RELOC(dest, I915_GEM_DOMAIN_INSTRUCTION, + I915_GEM_DOMAIN_INSTRUCTION, 0); + OUT_BATCH(0); + OUT_BATCH(val); + ADVANCE_BATCH(); + } else { BEGIN_BATCH(4); OUT_BATCH(cmd); OUT_BATCH(0); /* reserved */ - OUT_RELOC(target_buffer, I915_GEM_DOMAIN_INSTRUCTION, + OUT_RELOC(dest, I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, 0); OUT_BATCH(val); ADVANCE_BATCH(); + } +} + +static void +store_dword_loop(int devid, int divider) +{ + int i, val = 0; + uint32_t *buf; + igt_info("running storedw loop on render with stall every %i batch\n", divider); + + for (i = 0; i < SLOW_QUICK(0x2000, 0x10); i++) { + emit_store_dword_imm(devid, target_buffer, val); intel_batchbuffer_flush_on_ring(batch, I915_EXEC_BLT); + if (i % divider != 0) + goto cont; + drm_intel_bo_map(target_buffer, 0); buf = target_buffer->virtual; - if (buf[0] != val) { - fprintf(stderr, - "value mismatch: cur 0x%08x, stored 0x%08x\n", - buf[0], val); - exit(-1); - } + igt_assert_f(buf[0] == val, + "value mismatch: cur 0x%08x, stored 0x%08x\n", + buf[0], val); drm_intel_bo_unmap(target_buffer); +cont: val++; } drm_intel_bo_map(target_buffer, 0); buf = target_buffer->virtual; - printf("completed %d writes successfully, current value: 0x%08x\n", i, + igt_info("completed %d writes successfully, current value: 0x%08x\n", i, buf[0]); drm_intel_bo_unmap(target_buffer); } -int main(int argc, char **argv) +igt_simple_main { int fd; int devid; - if (argc != 1) { - fprintf(stderr, "usage: %s\n", argv[0]); - exit(-1); - } - fd = drm_open_any(); devid = intel_get_drm_devid(fd); has_ppgtt = gem_uses_aliasing_ppgtt(fd); - if (IS_GEN2(devid) || IS_GEN3(devid) || IS_GEN4(devid) || IS_GEN5(devid)) { - - fprintf(stderr, "MI_STORE_DATA can only use GTT address on gen4+/g33 and " - "needs snoopable mem on pre-gen6\n"); - return 77; - } + igt_skip_on_f(intel_gen(devid) < 6, + "MI_STORE_DATA can only use GTT address on gen4+/g33 and " + "needs snoopable mem on pre-gen6\n"); /* This only works with ppgtt */ - if (!has_ppgtt) { - fprintf(stderr, "no ppgtt detected, which is required\n"); - return 77; - } + igt_require(has_ppgtt); bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - if (!bufmgr) { - fprintf(stderr, "failed to init libdrm\n"); - exit(-1); - } + igt_assert(bufmgr); drm_intel_bufmgr_gem_enable_reuse(bufmgr); batch = intel_batchbuffer_alloc(bufmgr, devid); - if (!batch) { - fprintf(stderr, "failed to create batch buffer\n"); - exit(-1); - } + igt_assert(batch); target_buffer = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096); - if (!target_buffer) { - fprintf(stderr, "failed to alloc target buffer\n"); - exit(-1); - } + igt_assert(target_buffer); - store_dword_loop(); + store_dword_loop(devid, 1); + store_dword_loop(devid, 2); + if (!igt_run_in_simulation()) { + store_dword_loop(devid, 3); + store_dword_loop(devid, 5); + } drm_intel_bo_unreference(target_buffer); intel_batchbuffer_free(batch); drm_intel_bufmgr_destroy(bufmgr); close(fd); - - return 0; } diff --git a/tests/gem_storedw_loop_bsd.c b/tests/gem_storedw_loop_bsd.c index d7c61047..f89d522e 100644 --- a/tests/gem_storedw_loop_bsd.c +++ b/tests/gem_storedw_loop_bsd.c @@ -29,18 +29,18 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "intel_chipset.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; @@ -52,109 +52,108 @@ static int has_ppgtt = 0; */ static void -store_dword_loop(void) +emit_store_dword_imm(int devid, drm_intel_bo *dest, uint32_t val) { - int cmd, i, val = 0; - uint32_t *buf; - + int cmd; cmd = MI_STORE_DWORD_IMM; if (!has_ppgtt) cmd |= MI_MEM_VIRTUAL; - for (i = 0; i < 0x100000; i++) { + if (intel_gen(devid) >= 8) { + BEGIN_BATCH(4); + OUT_BATCH(cmd); + OUT_RELOC(dest, I915_GEM_DOMAIN_INSTRUCTION, + I915_GEM_DOMAIN_INSTRUCTION, 0); + OUT_BATCH(0); + OUT_BATCH(val); + ADVANCE_BATCH(); + } else { BEGIN_BATCH(4); OUT_BATCH(cmd); OUT_BATCH(0); /* reserved */ - OUT_RELOC(target_buffer, I915_GEM_DOMAIN_INSTRUCTION, + OUT_RELOC(dest, I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, 0); OUT_BATCH(val); ADVANCE_BATCH(); + } +} + +static void +store_dword_loop(int devid, int divider) +{ + int i, val = 0; + uint32_t *buf; + + igt_info("running storedw loop on render with stall every %i batch\n", divider); + for (i = 0; i < SLOW_QUICK(0x2000, 0x10); i++) { + emit_store_dword_imm(devid, target_buffer, val); intel_batchbuffer_flush_on_ring(batch, I915_EXEC_BSD); + if (i % divider != 0) + goto cont; + drm_intel_bo_map(target_buffer, 0); buf = target_buffer->virtual; - if (buf[0] != val) { - fprintf(stderr, - "value mismatch: cur 0x%08x, stored 0x%08x\n", - buf[0], val); - exit(-1); - } + igt_assert_f(buf[0] == val, + "value mismatch: cur 0x%08x, stored 0x%08x\n", + buf[0], val); drm_intel_bo_unmap(target_buffer); +cont: val++; } drm_intel_bo_map(target_buffer, 0); buf = target_buffer->virtual; - printf("completed %d writes successfully, current value: 0x%08x\n", i, + igt_info("completed %d writes successfully, current value: 0x%08x\n", i, buf[0]); drm_intel_bo_unmap(target_buffer); } -int main(int argc, char **argv) +igt_simple_main { int fd; int devid; - if (argc != 1) { - fprintf(stderr, "usage: %s\n", argv[0]); - exit(-1); - } - fd = drm_open_any(); devid = intel_get_drm_devid(fd); has_ppgtt = gem_uses_aliasing_ppgtt(fd); - if (IS_GEN2(devid) || IS_GEN3(devid) || IS_GEN4(devid) || IS_GEN5(devid)) { + igt_skip_on_f(intel_gen(devid) < 6, + "MI_STORE_DATA can only use GTT address on gen4+/g33 and " + "needs snoopable mem on pre-gen6\n"); - fprintf(stderr, "MI_STORE_DATA can only use GTT address on gen4+/g33 and " - "needs snoopable mem on pre-gen6\n"); - return 77; - } - - if (IS_GEN6(devid)) { - - fprintf(stderr, "MI_STORE_DATA broken on gen6 bsd\n"); - return 77; - } + igt_skip_on_f(intel_gen(devid) == 6, + "MI_STORE_DATA broken on gen6 bsd\n"); /* This only works with ppgtt */ - if (!has_ppgtt) { - fprintf(stderr, "no ppgtt detected, which is required\n"); - return 77; - } + igt_require(has_ppgtt); bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - if (!bufmgr) { - fprintf(stderr, "failed to init libdrm\n"); - exit(-1); - } + igt_assert(bufmgr); drm_intel_bufmgr_gem_enable_reuse(bufmgr); batch = intel_batchbuffer_alloc(bufmgr, devid); - if (!batch) { - fprintf(stderr, "failed to create batch buffer\n"); - exit(-1); - } + igt_assert(batch); target_buffer = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096); - if (!target_buffer) { - fprintf(stderr, "failed to alloc target buffer\n"); - exit(-1); - } + igt_assert(target_buffer); - store_dword_loop(); + store_dword_loop(devid, 1); + store_dword_loop(devid, 2); + if (!igt_run_in_simulation()) { + store_dword_loop(devid, 3); + store_dword_loop(devid, 5); + } drm_intel_bo_unreference(target_buffer); intel_batchbuffer_free(batch); drm_intel_bufmgr_destroy(bufmgr); close(fd); - - return 0; } diff --git a/tests/gem_storedw_loop_render.c b/tests/gem_storedw_loop_render.c index 19a41b65..9defc6d6 100644 --- a/tests/gem_storedw_loop_render.c +++ b/tests/gem_storedw_loop_render.c @@ -29,18 +29,18 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "intel_chipset.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; @@ -52,97 +52,102 @@ static int has_ppgtt = 0; */ static void -store_dword_loop(void) +emit_store_dword_imm(int devid, drm_intel_bo *dest, uint32_t val) { - int cmd, i, val = 0; - uint32_t *buf; - + int cmd; cmd = MI_STORE_DWORD_IMM; if (!has_ppgtt) cmd |= MI_MEM_VIRTUAL; - for (i = 0; i < 0x100000; i++) { + if (intel_gen(devid) >= 8) { + BEGIN_BATCH(4); + OUT_BATCH(cmd); + OUT_RELOC(dest, I915_GEM_DOMAIN_INSTRUCTION, + I915_GEM_DOMAIN_INSTRUCTION, 0); + OUT_BATCH(0); + OUT_BATCH(val); + ADVANCE_BATCH(); + } else { BEGIN_BATCH(4); OUT_BATCH(cmd); OUT_BATCH(0); /* reserved */ - OUT_RELOC(target_buffer, I915_GEM_DOMAIN_INSTRUCTION, + OUT_RELOC(dest, I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, 0); OUT_BATCH(val); ADVANCE_BATCH(); + } +} + +static void +store_dword_loop(int devid, int divider) +{ + int i, val = 0; + uint32_t *buf; + + igt_info("running storedw loop on render with stall every %i batch\n", divider); + for (i = 0; i < SLOW_QUICK(0x2000, 0x10); i++) { + emit_store_dword_imm(devid, target_buffer, val); intel_batchbuffer_flush_on_ring(batch, 0); + if (i % divider != 0) + goto cont; + drm_intel_bo_map(target_buffer, 0); buf = target_buffer->virtual; - if (buf[0] != val) { - fprintf(stderr, - "value mismatch: cur 0x%08x, stored 0x%08x\n", - buf[0], val); - exit(-1); - } + igt_assert_f(buf[0] == val, + "value mismatch: cur 0x%08x, stored 0x%08x\n", + buf[0], val); drm_intel_bo_unmap(target_buffer); +cont: val++; } drm_intel_bo_map(target_buffer, 0); buf = target_buffer->virtual; - printf("completed %d writes successfully, current value: 0x%08x\n", i, + igt_info("completed %d writes successfully, current value: 0x%08x\n", i, buf[0]); drm_intel_bo_unmap(target_buffer); } -int main(int argc, char **argv) +igt_simple_main { int fd; int devid; - if (argc != 1) { - fprintf(stderr, "usage: %s\n", argv[0]); - exit(-1); - } - fd = drm_open_any(); devid = intel_get_drm_devid(fd); has_ppgtt = gem_uses_aliasing_ppgtt(fd); - if (IS_GEN2(devid) || IS_GEN3(devid) || IS_GEN4(devid) || IS_GEN5(devid)) { - - fprintf(stderr, "MI_STORE_DATA can only use GTT address on gen4+/g33 and " - "needs snoopable mem on pre-gen6\n"); - return 77; - } + igt_skip_on_f(intel_gen(devid) < 6, + "MI_STORE_DATA can only use GTT address on gen4+/g33 and " + "needs snoopable mem on pre-gen6\n"); bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - if (!bufmgr) { - fprintf(stderr, "failed to init libdrm\n"); - exit(-1); - } + igt_assert(bufmgr); drm_intel_bufmgr_gem_enable_reuse(bufmgr); batch = intel_batchbuffer_alloc(bufmgr, devid); - if (!batch) { - fprintf(stderr, "failed to create batch buffer\n"); - exit(-1); - } + igt_assert(batch); target_buffer = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096); - if (!target_buffer) { - fprintf(stderr, "failed to alloc target buffer\n"); - exit(-1); - } + igt_assert(target_buffer); - store_dword_loop(); + store_dword_loop(devid, 1); + store_dword_loop(devid, 2); + if (!igt_run_in_simulation()) { + store_dword_loop(devid, 3); + store_dword_loop(devid, 5); + } drm_intel_bo_unreference(target_buffer); intel_batchbuffer_free(batch); drm_intel_bufmgr_destroy(bufmgr); close(fd); - - return 0; } diff --git a/tests/gem_storedw_loop_vebox.c b/tests/gem_storedw_loop_vebox.c new file mode 100644 index 00000000..c94a6770 --- /dev/null +++ b/tests/gem_storedw_loop_vebox.c @@ -0,0 +1,130 @@ +/* + * Copyright © 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Xiang, Haihao <haihao.xiang@intel.com> (based on gem_store_dw_loop_*) + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> +#include "drm.h" +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_io.h" +#include "intel_chipset.h" + +#define LOCAL_I915_EXEC_VEBOX (4<<0) + +static drm_intel_bufmgr *bufmgr; +struct intel_batchbuffer *batch; +static drm_intel_bo *target_buffer; + +/* + * Testcase: Basic vebox MI check using MI_STORE_DATA_IMM + */ + +static void +store_dword_loop(int divider) +{ + int cmd, i, val = 0; + uint32_t *buf; + + igt_info("running storedw loop on blt with stall every %i batch\n", divider); + + cmd = MI_STORE_DWORD_IMM; + + for (i = 0; i < SLOW_QUICK(0x2000, 0x10); i++) { + BEGIN_BATCH(4); + OUT_BATCH(cmd); + if (intel_gen(batch->devid) < 8) + OUT_BATCH(0); /* reserved */ + OUT_RELOC(target_buffer, I915_GEM_DOMAIN_INSTRUCTION, + I915_GEM_DOMAIN_INSTRUCTION, 0); + BLIT_RELOC_UDW(batch->devid); + OUT_BATCH(val); + ADVANCE_BATCH(); + + intel_batchbuffer_flush_on_ring(batch, LOCAL_I915_EXEC_VEBOX); + + if (i % divider != 0) + goto cont; + + drm_intel_bo_map(target_buffer, 0); + + buf = target_buffer->virtual; + igt_assert_cmpint (buf[0], ==, val); + + drm_intel_bo_unmap(target_buffer); + +cont: + val++; + } + + drm_intel_bo_map(target_buffer, 0); + buf = target_buffer->virtual; + + igt_info("completed %d writes successfully, current value: 0x%08x\n", i, + buf[0]); + drm_intel_bo_unmap(target_buffer); +} + +igt_simple_main +{ + int fd; + + fd = drm_open_any(); + + igt_require(gem_has_vebox(fd)); + igt_require(gem_uses_aliasing_ppgtt(fd)); + + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + igt_assert(bufmgr); + drm_intel_bufmgr_gem_enable_reuse(bufmgr); + + batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); + igt_require(batch); + + target_buffer = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096); + igt_require(target_buffer); + + store_dword_loop(1); + store_dword_loop(2); + if (!igt_run_in_simulation()) { + store_dword_loop(3); + store_dword_loop(5); + } + + drm_intel_bo_unreference(target_buffer); + intel_batchbuffer_free(batch); + drm_intel_bufmgr_destroy(bufmgr); + + close(fd); +} diff --git a/tests/gem_stress.c b/tests/gem_stress.c index 69239ac1..e6a6ce69 100644 --- a/tests/gem_stress.c +++ b/tests/gem_stress.c @@ -49,7 +49,26 @@ * In short: designed for maximum evilness. */ -#include "rendercopy.h" +#include <stdlib.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <getopt.h> + +#include <drm.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_io.h" +#include "intel_chipset.h" +#include "igt_aux.h" #define CMD_POLY_STIPPLE_OFFSET 0x7906 @@ -100,7 +119,7 @@ struct option_struct options; #define BUSY_BUF_SIZE (256*4096) #define TILE_BYTES(size) ((size)*(size)*sizeof(uint32_t)) -static struct scratch_buf buffers[2][MAX_BUFS]; +static struct igt_buf buffers[2][MAX_BUFS]; /* tile i is at logical position tile_permutation[i] */ static unsigned *tile_permutation; static unsigned num_buffers = 0; @@ -116,9 +135,9 @@ struct { unsigned max_failed_reads; } stats; -static void tile2xy(struct scratch_buf *buf, unsigned tile, unsigned *x, unsigned *y) +static void tile2xy(struct igt_buf *buf, unsigned tile, unsigned *x, unsigned *y) { - assert(tile < buf->num_tiles); + igt_assert(tile < buf->num_tiles); *x = (tile*options.tile_size) % (buf->stride/sizeof(uint32_t)); *y = ((tile*options.tile_size) / (buf->stride/sizeof(uint32_t))) * options.tile_size; } @@ -141,20 +160,18 @@ static void emit_blt(drm_intel_bo *src_bo, uint32_t src_tiling, unsigned src_pit } /* copy lower half to upper half */ - BEGIN_BATCH(8); - OUT_BATCH(XY_SRC_COPY_BLT_CMD | - XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB | - cmd_bits); + BLIT_COPY_BATCH_START(devid, cmd_bits); OUT_BATCH((3 << 24) | /* 32 bits */ (0xcc << 16) | /* copy ROP */ dst_pitch); OUT_BATCH(dst_y << 16 | dst_x); OUT_BATCH((dst_y+h) << 16 | (dst_x+w)); OUT_RELOC_FENCED(dst_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(devid); OUT_BATCH(src_y << 16 | src_x); OUT_BATCH(src_pitch); OUT_RELOC_FENCED(src_bo, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(devid); ADVANCE_BATCH(); if (IS_GEN6(devid) || IS_GEN7(devid)) { @@ -173,21 +190,21 @@ static void keep_gpu_busy(void) int tmp; tmp = 1 << gpu_busy_load; - assert(tmp <= 1024); + igt_assert(tmp <= 1024); emit_blt(busy_bo, 0, 4096, 0, 0, tmp, 128, busy_bo, 0, 4096, 0, 128); } -static void set_to_cpu_domain(struct scratch_buf *buf, int writing) +static void set_to_cpu_domain(struct igt_buf *buf, int writing) { gem_set_domain(drm_fd, buf->bo->handle, I915_GEM_DOMAIN_CPU, writing ? I915_GEM_DOMAIN_CPU : 0); } static unsigned int copyfunc_seq = 0; -static void (*copyfunc)(struct scratch_buf *src, unsigned src_x, unsigned src_y, - struct scratch_buf *dst, unsigned dst_x, unsigned dst_y, +static void (*copyfunc)(struct igt_buf *src, unsigned src_x, unsigned src_y, + struct igt_buf *dst, unsigned dst_x, unsigned dst_y, unsigned logical_tile_no); /* stride, x, y in units of uint32_t! */ @@ -209,7 +226,7 @@ static void cpucpy2d(uint32_t *src, unsigned src_stride, unsigned src_x, unsigne printf("mismatch at tile %i pos %i, read %i, expected %i, diff %i\n", logical_tile_no, i*options.tile_size + j, tmp, expect, (int) tmp - expect); if (options.trace_tile >= 0 && options.fail) - exit(1); + igt_fail(1); failed++; } /* when not aborting, correct any errors */ @@ -217,7 +234,7 @@ static void cpucpy2d(uint32_t *src, unsigned src_stride, unsigned src_x, unsigne } } if (failed && options.fail) - exit(1); + igt_fail(1); if (failed > stats.max_failed_reads) stats.max_failed_reads = failed; @@ -225,11 +242,11 @@ static void cpucpy2d(uint32_t *src, unsigned src_stride, unsigned src_x, unsigne stats.num_failed++; } -static void cpu_copyfunc(struct scratch_buf *src, unsigned src_x, unsigned src_y, - struct scratch_buf *dst, unsigned dst_x, unsigned dst_y, +static void cpu_copyfunc(struct igt_buf *src, unsigned src_x, unsigned src_y, + struct igt_buf *dst, unsigned dst_x, unsigned dst_y, unsigned logical_tile_no) { - assert(batch->ptr == batch->buffer); + igt_assert(batch->ptr == batch->buffer); if (options.ducttape) drm_intel_bo_wait_rendering(dst->bo); @@ -244,14 +261,14 @@ static void cpu_copyfunc(struct scratch_buf *src, unsigned src_x, unsigned src_y logical_tile_no); } -static void prw_copyfunc(struct scratch_buf *src, unsigned src_x, unsigned src_y, - struct scratch_buf *dst, unsigned dst_x, unsigned dst_y, +static void prw_copyfunc(struct igt_buf *src, unsigned src_x, unsigned src_y, + struct igt_buf *dst, unsigned dst_x, unsigned dst_y, unsigned logical_tile_no) { uint32_t tmp_tile[options.tile_size*options.tile_size]; int i; - assert(batch->ptr == batch->buffer); + igt_assert(batch->ptr == batch->buffer); if (options.ducttape) drm_intel_bo_wait_rendering(dst->bo); @@ -288,8 +305,8 @@ static void prw_copyfunc(struct scratch_buf *src, unsigned src_x, unsigned src_y } } -static void blitter_copyfunc(struct scratch_buf *src, unsigned src_x, unsigned src_y, - struct scratch_buf *dst, unsigned dst_x, unsigned dst_y, +static void blitter_copyfunc(struct igt_buf *src, unsigned src_x, unsigned src_y, + struct igt_buf *dst, unsigned dst_x, unsigned dst_y, unsigned logical_tile_no) { static unsigned keep_gpu_busy_counter = 0; @@ -318,37 +335,27 @@ static void blitter_copyfunc(struct scratch_buf *src, unsigned src_x, unsigned s } } -static void render_copyfunc(struct scratch_buf *src, unsigned src_x, unsigned src_y, - struct scratch_buf *dst, unsigned dst_x, unsigned dst_y, +static void render_copyfunc(struct igt_buf *src, unsigned src_x, unsigned src_y, + struct igt_buf *dst, unsigned dst_x, unsigned dst_y, unsigned logical_tile_no) { static unsigned keep_gpu_busy_counter = 0; + igt_render_copyfunc_t rendercopy = igt_get_render_copyfunc(devid); /* check both edges of the fence usage */ if (keep_gpu_busy_counter & 1) keep_gpu_busy(); - if (IS_GEN2(devid)) - gen2_render_copyfunc(batch, - src, src_x, src_y, - options.tile_size, options.tile_size, - dst, dst_x, dst_y); - else if (IS_GEN3(devid)) - gen3_render_copyfunc(batch, - src, src_x, src_y, - options.tile_size, options.tile_size, - dst, dst_x, dst_y); - else if (IS_GEN6(devid)) - gen6_render_copyfunc(batch, - src, src_x, src_y, - options.tile_size, options.tile_size, - dst, dst_x, dst_y); - else if (IS_GEN7(devid)) - gen7_render_copyfunc(batch, - src, src_x, src_y, - options.tile_size, options.tile_size, - dst, dst_x, dst_y); - else + if (rendercopy) { + /* + * Flush outstanding blts so that they don't end up on + * the render ring when that's not allowed (gen6+). + */ + intel_batchbuffer_flush(batch); + rendercopy(batch, NULL, src, src_x, src_y, + options.tile_size, options.tile_size, + dst, dst_x, dst_y); + } else blitter_copyfunc(src, src_x, src_y, dst, dst_x, dst_y, logical_tile_no); @@ -453,32 +460,32 @@ static void fan_in_and_check(void) } } -static void sanitize_stride(struct scratch_buf *buf) +static void sanitize_stride(struct igt_buf *buf) { - if (buf_height(buf) > options.max_dimension) + if (igt_buf_height(buf) > options.max_dimension) buf->stride = buf->size / options.max_dimension; - if (buf_height(buf) < options.tile_size) + if (igt_buf_height(buf) < options.tile_size) buf->stride = buf->size / options.tile_size; - if (buf_width(buf) < options.tile_size) + if (igt_buf_width(buf) < options.tile_size) buf->stride = options.tile_size * sizeof(uint32_t); - assert(buf->stride <= 8192); - assert(buf_width(buf) <= options.max_dimension); - assert(buf_height(buf) <= options.max_dimension); + igt_assert(buf->stride <= 8192); + igt_assert(igt_buf_width(buf) <= options.max_dimension); + igt_assert(igt_buf_height(buf) <= options.max_dimension); - assert(buf_width(buf) >= options.tile_size); - assert(buf_height(buf) >= options.tile_size); + igt_assert(igt_buf_width(buf) >= options.tile_size); + igt_assert(igt_buf_height(buf) >= options.tile_size); } -static void init_buffer(struct scratch_buf *buf, unsigned size) +static void init_buffer(struct igt_buf *buf, unsigned size) { buf->bo = drm_intel_bo_alloc(bufmgr, "tiled bo", size, 4096); buf->size = size; - assert(buf->bo); + igt_assert(buf->bo); buf->tiling = I915_TILING_NONE; buf->stride = 4096; @@ -499,12 +506,12 @@ static void init_buffer(struct scratch_buf *buf, unsigned size) static void exchange_buf(void *array, unsigned i, unsigned j) { - struct scratch_buf *buf_arr, tmp; + struct igt_buf *buf_arr, tmp; buf_arr = array; - memcpy(&tmp, &buf_arr[i], sizeof(struct scratch_buf)); - memcpy(&buf_arr[i], &buf_arr[j], sizeof(struct scratch_buf)); - memcpy(&buf_arr[j], &tmp, sizeof(struct scratch_buf)); + memcpy(&tmp, &buf_arr[i], sizeof(struct igt_buf)); + memcpy(&buf_arr[i], &buf_arr[j], sizeof(struct igt_buf)); + memcpy(&buf_arr[j], &tmp, sizeof(struct igt_buf)); } @@ -513,7 +520,7 @@ static void init_set(unsigned set) long int r; int i; - drmtest_permute_array(buffers[set], num_buffers, exchange_buf); + igt_permute_array(buffers[set], num_buffers, exchange_buf); if (current_set == 1 && options.gpu_busy_load == 0) { gpu_busy_load++; @@ -576,7 +583,7 @@ static void copy_tiles(unsigned *permutation) { unsigned src_tile, src_buf_idx, src_x, src_y; unsigned dst_tile, dst_buf_idx, dst_x, dst_y; - struct scratch_buf *src_buf, *dst_buf; + struct igt_buf *src_buf, *dst_buf; int i, idx; for (i = 0; i < num_total_tiles; i++) { /* tile_permutation is independent of current_permutation, so @@ -618,22 +625,6 @@ static void copy_tiles(unsigned *permutation) intel_batchbuffer_flush(batch); } -static int get_num_fences(void) -{ - drm_i915_getparam_t gp; - int ret, val; - - gp.param = I915_PARAM_NUM_FENCES_AVAIL; - gp.value = &val; - ret = drmIoctl(drm_fd, DRM_IOCTL_I915_GETPARAM, &gp); - assert (ret == 0); - - printf ("total %d fences\n", val); - assert(val > 4); - - return val - 2; -} - static void sanitize_tiles_per_buf(void) { if (options.tiles_per_buf > options.scratch_buf_size / TILE_BYTES(options.tile_size)) @@ -665,6 +656,7 @@ static void parse_options(int argc, char **argv) {"tile-size", 1, 0, TILESZ}, #define CHCK_RENDER 0xdead0003 {"check-render-cpyfn", 0, 0, CHCK_RENDER}, + {NULL, 0, 0, 0}, }; options.scratch_buf_size = 256*4096; @@ -813,7 +805,8 @@ static void init(void) bufmgr = drm_intel_bufmgr_gem_init(drm_fd, 4096); drm_intel_bufmgr_gem_enable_reuse(bufmgr); drm_intel_bufmgr_gem_enable_fenced_relocs(bufmgr); - num_fences = get_num_fences(); + num_fences = gem_available_fences(drm_fd); + igt_assert(num_fences > 4); batch = intel_batchbuffer_alloc(bufmgr, devid); busy_bo = drm_intel_bo_alloc(bufmgr, "tiled bo", BUSY_BUF_SIZE, 4096); @@ -834,7 +827,7 @@ static void init(void) static void check_render_copyfunc(void) { - struct scratch_buf src, dst; + struct igt_buf src, dst; uint32_t *ptr; int i, j, pass; @@ -845,10 +838,10 @@ static void check_render_copyfunc(void) init_buffer(&dst, options.scratch_buf_size); for (pass = 0; pass < 16; pass++) { - int sx = random() % (buf_width(&src)-options.tile_size); - int sy = random() % (buf_height(&src)-options.tile_size); - int dx = random() % (buf_width(&dst)-options.tile_size); - int dy = random() % (buf_height(&dst)-options.tile_size); + int sx = random() % (igt_buf_width(&src)-options.tile_size); + int sy = random() % (igt_buf_height(&src)-options.tile_size); + int dx = random() % (igt_buf_width(&dst)-options.tile_size); + int dy = random() % (igt_buf_height(&dst)-options.tile_size); if (options.use_cpu_maps) set_to_cpu_domain(&src, 1); @@ -889,7 +882,7 @@ int main(int argc, char **argv) /* start our little helper early before too may allocations occur */ if (options.use_signal_helper) - drmtest_fork_signal_helper(); + igt_fork_signal_helper(); init(); @@ -898,9 +891,9 @@ int main(int argc, char **argv) tile_permutation = malloc(num_total_tiles*sizeof(uint32_t)); current_permutation = malloc(num_total_tiles*sizeof(uint32_t)); tmp_permutation = malloc(num_total_tiles*sizeof(uint32_t)); - assert(tile_permutation); - assert(current_permutation); - assert(tmp_permutation); + igt_assert(tile_permutation); + igt_assert(current_permutation); + igt_assert(tmp_permutation); fan_out(); @@ -916,7 +909,7 @@ int main(int argc, char **argv) for (j = 0; j < num_total_tiles; j++) current_permutation[j] = j; - drmtest_permute_array(current_permutation, num_total_tiles, exchange_uint); + igt_permute_array(current_permutation, num_total_tiles, exchange_uint); copy_tiles(current_permutation); @@ -939,7 +932,7 @@ int main(int argc, char **argv) close(drm_fd); - drmtest_stop_signal_helper(); + igt_stop_signal_helper(); return 0; } diff --git a/tests/gem_threaded_access_tiled.c b/tests/gem_threaded_access_tiled.c new file mode 100644 index 00000000..3752a1f6 --- /dev/null +++ b/tests/gem_threaded_access_tiled.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Mika Kuoppala <mika.kuoppala@intel.com> + */ + +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <pthread.h> + +#include "drmtest.h" +#include "ioctl_wrappers.h" +#include "intel_bufmgr.h" + +/* Testcase: check parallel access to tiled memory + * + * Parallel access to tiled memory caused sigbus + */ + +#define NUM_THREADS 2 +#define WIDTH 4096 +#define HEIGHT 4096 + +struct thread_ctx { + drm_intel_bo *bo; +}; + +static drm_intel_bufmgr *bufmgr; +static struct thread_ctx tctx[NUM_THREADS]; + +static void *copy_fn(void *p) +{ + unsigned char *buf; + struct thread_ctx *c = p; + + buf = malloc(WIDTH * HEIGHT); + if (buf == NULL) + return (void *)1; + + memcpy(buf, c->bo->virtual, WIDTH * HEIGHT); + + free(buf); + return (void *)0; +} + +static int copy_tile_threaded(drm_intel_bo *bo) +{ + int i; + int r; + pthread_t thr[NUM_THREADS]; + void *status; + + for (i = 0; i < NUM_THREADS; i++) { + tctx[i].bo = bo; + r = pthread_create(&thr[i], NULL, copy_fn, (void *)&tctx[i]); + igt_assert(r == 0); + } + + for (i = 0; i < NUM_THREADS; i++) { + pthread_join(thr[i], &status); + igt_assert(status == 0); + } + + return 0; +} + +igt_simple_main +{ + int fd; + drm_intel_bo *bo; + uint32_t tiling_mode = I915_TILING_Y; + unsigned long pitch = 0; + int r; + + igt_skip_on_simulation(); + + fd = drm_open_any(); + igt_assert(fd >= 0); + + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + igt_assert(bufmgr); + + bo = drm_intel_bo_alloc_tiled(bufmgr, "mmap bo", WIDTH, HEIGHT, 1, + &tiling_mode, &pitch, 0); + igt_assert(bo); + + r = drm_intel_gem_bo_map_gtt(bo); + igt_assert(!r); + + r = copy_tile_threaded(bo); + igt_assert(!r); + + r = drm_intel_gem_bo_unmap_gtt(bo); + igt_assert(!r); + + drm_intel_bo_unreference(bo); + drm_intel_bufmgr_destroy(bufmgr); + + close(fd); +} diff --git a/tests/gem_tiled_blits.c b/tests/gem_tiled_blits.c index 86c9a886..cb135ce4 100644 --- a/tests/gem_tiled_blits.c +++ b/tests/gem_tiled_blits.c @@ -44,18 +44,19 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> -#include "drm.h" -#include "i915_drm.h" + +#include <drm.h> + +#include "ioctl_wrappers.h" #include "drmtest.h" -#include "intel_bufmgr.h" -#include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_chipset.h" +#include "intel_io.h" +#include "igt_aux.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; @@ -67,23 +68,22 @@ create_bo(uint32_t start_val) drm_intel_bo *bo, *linear_bo; uint32_t *linear; uint32_t tiling = I915_TILING_X; - int ret, i; + int i; bo = drm_intel_bo_alloc(bufmgr, "tiled bo", 1024 * 1024, 4096); - ret = drm_intel_bo_set_tiling(bo, &tiling, width * 4); - assert(ret == 0); - assert(tiling == I915_TILING_X); + do_or_die(drm_intel_bo_set_tiling(bo, &tiling, width * 4)); + igt_assert(tiling == I915_TILING_X); linear_bo = drm_intel_bo_alloc(bufmgr, "linear src", 1024 * 1024, 4096); /* Fill the BO with dwords starting at start_val */ - drm_intel_bo_map(linear_bo, 1); + do_or_die(drm_intel_bo_map(linear_bo, 1)); linear = linear_bo->virtual; for (i = 0; i < 1024 * 1024 / 4; i++) linear[i] = start_val++; drm_intel_bo_unmap(linear_bo); - intel_copy_bo (batch, bo, linear_bo, width, height); + intel_copy_bo (batch, bo, linear_bo, width*height*4); drm_intel_bo_unreference(linear_bo); @@ -99,18 +99,16 @@ check_bo(drm_intel_bo *bo, uint32_t start_val) linear_bo = drm_intel_bo_alloc(bufmgr, "linear dst", 1024 * 1024, 4096); - intel_copy_bo(batch, linear_bo, bo, width, height); + intel_copy_bo(batch, linear_bo, bo, width*height*4); - drm_intel_bo_map(linear_bo, 0); + do_or_die(drm_intel_bo_map(linear_bo, 0)); linear = linear_bo->virtual; for (i = 0; i < 1024 * 1024 / 4; i++) { - if (linear[i] != start_val) { - fprintf(stderr, "Expected 0x%08x, found 0x%08x " - "at offset 0x%08x\n", - start_val, linear[i], i * 4); - abort(); - } + igt_assert_f(linear[i] == start_val, + "Expected 0x%08x, found 0x%08x " + "at offset 0x%08x\n", + start_val, linear[i], i * 4); start_val++; } drm_intel_bo_unmap(linear_bo); @@ -118,47 +116,26 @@ check_bo(drm_intel_bo *bo, uint32_t start_val) drm_intel_bo_unreference(linear_bo); } -int main(int argc, char **argv) +static void run_test(int count) { drm_intel_bo **bo; uint32_t *bo_start_val; uint32_t start = 0; - int i, fd, count; - - fd = drm_open_any(); - - count = 0; - if (argc > 1) - count = atoi(argv[1]); - if (count == 0) { - count = 3 * gem_aperture_size(fd) / (1024*1024) / 2; - count += (count & 1) == 0; - } - - if (count > intel_get_total_ram_mb() * 9 / 10) { - count = intel_get_total_ram_mb() * 9 / 10; - printf("not enough RAM to run test, reducing buffer count\n"); - } - - printf("Using %d 1MiB buffers\n", count); + int i; bo = malloc(sizeof(drm_intel_bo *)*count); bo_start_val = malloc(sizeof(uint32_t)*count); - bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - drm_intel_bufmgr_gem_enable_reuse(bufmgr); - batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); - for (i = 0; i < count; i++) { bo[i] = create_bo(start); bo_start_val[i] = start; start += 1024 * 1024 / 4; } - printf("Verifying initialisation...\n"); + igt_info("Verifying initialisation...\n"); for (i = 0; i < count; i++) check_bo(bo[i], bo_start_val[i]); - printf("Cyclic blits, forward...\n"); + igt_info("Cyclic blits, forward...\n"); for (i = 0; i < count * 4; i++) { int src = i % count; int dst = (i+1) % count; @@ -166,13 +143,21 @@ int main(int argc, char **argv) if (src == dst) continue; - intel_copy_bo(batch, bo[dst], bo[src], width, height); + intel_copy_bo(batch, bo[dst], bo[src], width*height*4); bo_start_val[dst] = bo_start_val[src]; } for (i = 0; i < count; i++) check_bo(bo[i], bo_start_val[i]); - printf("Cyclic blits, backward...\n"); + if (igt_run_in_simulation()) { + for (i = 0; i < count; i++) + drm_intel_bo_unreference(bo[i]); + free(bo_start_val); + free(bo); + return; + } + + igt_info("Cyclic blits, backward...\n"); for (i = 0; i < count * 4; i++) { int src = (i+1) % count; int dst = i % count; @@ -180,13 +165,13 @@ int main(int argc, char **argv) if (src == dst) continue; - intel_copy_bo(batch, bo[dst], bo[src], width, height); + intel_copy_bo(batch, bo[dst], bo[src], width*height*4); bo_start_val[dst] = bo_start_val[src]; } for (i = 0; i < count; i++) check_bo(bo[i], bo_start_val[i]); - printf("Random blits...\n"); + igt_info("Random blits...\n"); for (i = 0; i < count * 4; i++) { int src = random() % count; int dst = random() % count; @@ -194,21 +179,69 @@ int main(int argc, char **argv) if (src == dst) continue; - intel_copy_bo(batch, bo[dst], bo[src], width, height); + intel_copy_bo(batch, bo[dst], bo[src], width*height*4); bo_start_val[dst] = bo_start_val[src]; } - for (i = 0; i < count; i++) - check_bo(bo[i], bo_start_val[i]); - for (i = 0; i < count; i++) { + check_bo(bo[i], bo_start_val[i]); drm_intel_bo_unreference(bo[i]); - bo[i] = NULL; } - intel_batchbuffer_free(batch); - drm_intel_bufmgr_destroy(bufmgr); + free(bo_start_val); + free(bo); +} + +int fd; + +int main(int argc, char **argv) +{ + int count = 0; + + igt_subtest_init(argc, argv); + + igt_fixture { + fd = drm_open_any(); + + if (igt_run_in_simulation()) + count = 2; + if (argc > 1) + count = atoi(argv[1]); + if (count == 0) { + count = 3 * gem_aperture_size(fd) / (1024*1024) / 2; + count += (count & 1) == 0; + } else if (count < 2) { + fprintf(stderr, "count must be >= 2\n"); + return 1; + } + + if (count > intel_get_total_ram_mb() * 9 / 10) { + count = intel_get_total_ram_mb() * 9 / 10; + igt_info("not enough RAM to run test, reducing buffer count\n"); + } - close(fd); + igt_info("Using %d 1MiB buffers\n", count); + + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + drm_intel_bufmgr_gem_enable_reuse(bufmgr); + drm_intel_bufmgr_gem_set_vma_cache_size(bufmgr, 32); + batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); + } + + igt_subtest("normal") + run_test(count); + + igt_subtest("interruptible") { + igt_fork_signal_helper(); + run_test(count); + igt_stop_signal_helper(); + } + + igt_fixture { + intel_batchbuffer_free(batch); + drm_intel_bufmgr_destroy(bufmgr); + + close(fd); + } - return 0; + igt_exit(); } diff --git a/tests/gem_tiled_fence_blits.c b/tests/gem_tiled_fence_blits.c index dc654793..e3f322e3 100644 --- a/tests/gem_tiled_fence_blits.c +++ b/tests/gem_tiled_fence_blits.c @@ -44,18 +44,21 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> -#include "drm.h" -#include "i915_drm.h" + +#include <drm.h> + +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "intel_chipset.h" +#include "igt_aux.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; @@ -71,8 +74,8 @@ create_bo(int fd, uint32_t start_val) bo = drm_intel_bo_alloc(bufmgr, "tiled bo", 1024 * 1024, 4096); ret = drm_intel_bo_set_tiling(bo, &tiling, width * 4); - assert(ret == 0); - assert(tiling == I915_TILING_X); + igt_assert(ret == 0); + igt_assert(tiling == I915_TILING_X); /* Fill the BO with dwords starting at start_val */ for (i = 0; i < 1024 * 1024 / 4; i++) @@ -91,31 +94,31 @@ check_bo(int fd, drm_intel_bo *bo, uint32_t start_val) gem_read(fd, bo->handle, 0, linear, sizeof(linear)); for (i = 0; i < 1024 * 1024 / 4; i++) { - if (linear[i] != start_val) { - fprintf(stderr, "Expected 0x%08x, found 0x%08x " - "at offset 0x%08x\n", - start_val, linear[i], i * 4); - abort(); - } + igt_assert_f(linear[i] == start_val, + "Expected 0x%08x, found 0x%08x " + "at offset 0x%08x\n", + start_val, linear[i], i * 4); start_val++; } } -int main(int argc, char **argv) +igt_simple_main { drm_intel_bo *bo[4096]; uint32_t bo_start_val[4096]; uint32_t start = 0; int fd, i, count; + igt_skip_on_simulation(); + fd = drm_open_any(); count = 3 * gem_aperture_size(fd) / (1024*1024) / 2; if (count > intel_get_total_ram_mb() * 9 / 10) { count = intel_get_total_ram_mb() * 9 / 10; - printf("not enough RAM to run test, reducing buffer count\n"); + igt_info("not enough RAM to run test, reducing buffer count\n"); } count |= 1; - printf("Using %d 1MiB buffers\n", count); + igt_info("Using %d 1MiB buffers\n", count); bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); drm_intel_bufmgr_gem_enable_reuse(bufmgr); @@ -126,7 +129,7 @@ int main(int argc, char **argv) bo_start_val[i] = start; /* - printf("Creating bo %d\n", i); + igt_info("Creating bo %d\n", i); check_bo(bo[i], bo_start_val[i]); */ @@ -135,7 +138,7 @@ int main(int argc, char **argv) for (i = 0; i < count; i++) { int src = count - i - 1; - intel_copy_bo(batch, bo[i], bo[src], width, height); + intel_copy_bo(batch, bo[i], bo[src], width*height*4); bo_start_val[i] = bo_start_val[src]; } @@ -146,18 +149,18 @@ int main(int argc, char **argv) if (src == dst) continue; - intel_copy_bo(batch, bo[dst], bo[src], width, height); + intel_copy_bo(batch, bo[dst], bo[src], width*height*4); bo_start_val[dst] = bo_start_val[src]; /* check_bo(bo[dst], bo_start_val[dst]); - printf("%d: copy bo %d to %d\n", i, src, dst); + igt_info("%d: copy bo %d to %d\n", i, src, dst); */ } for (i = 0; i < count; i++) { /* - printf("check %d\n", i); + igt_info("check %d\n", i); */ check_bo(fd, bo[i], bo_start_val[i]); @@ -169,6 +172,4 @@ int main(int argc, char **argv) drm_intel_bufmgr_destroy(bufmgr); close(fd); - - return 0; } diff --git a/tests/gem_tiled_partial_pwrite_pread.c b/tests/gem_tiled_partial_pwrite_pread.c index bd0d4e09..f22e834b 100644 --- a/tests/gem_tiled_partial_pwrite_pread.c +++ b/tests/gem_tiled_partial_pwrite_pread.c @@ -28,18 +28,19 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> -#include "drm.h" -#include "i915_drm.h" + +#include <drm.h> + +#include "ioctl_wrappers.h" #include "drmtest.h" -#include "intel_bufmgr.h" -#include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_chipset.h" +#include "intel_io.h" +#include "igt_aux.h" /* * Testcase: pwrite/pread consistency when touching partial cachelines @@ -83,20 +84,18 @@ copy_bo(drm_intel_bo *src, int src_tiled, cmd_bits |= XY_SRC_COPY_BLT_SRC_TILED; } - BEGIN_BATCH(8); - OUT_BATCH(XY_SRC_COPY_BLT_CMD | - XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB | - cmd_bits); + BLIT_COPY_BATCH_START(devid, cmd_bits); OUT_BATCH((3 << 24) | /* 32 bits */ (0xcc << 16) | /* copy ROP */ dst_pitch); OUT_BATCH(0 << 16 | 0); OUT_BATCH(BO_SIZE/scratch_pitch << 16 | 1024); OUT_RELOC_FENCED(dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(devid); OUT_BATCH(0 << 16 | 0); OUT_BATCH(src_pitch); OUT_RELOC_FENCED(src, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(devid); ADVANCE_BATCH(); intel_batchbuffer_flush(batch); @@ -118,45 +117,20 @@ blt_bo_fill(drm_intel_bo *tmp_bo, drm_intel_bo *bo, int val) if (bo->offset < mappable_gtt_limit && (IS_G33(devid) || intel_gen(devid) >= 4)) - drmtest_trash_aperture(); + igt_trash_aperture(); copy_bo(tmp_bo, 0, bo, 1); } #define MAX_BLT_SIZE 128 #define ROUNDS 200 -int main(int argc, char **argv) +uint8_t tmp[BO_SIZE]; +uint8_t compare_tmp[BO_SIZE]; + +static void test_partial_reads(void) { int i, j; - uint8_t tmp[BO_SIZE]; - uint8_t compare_tmp[BO_SIZE]; - uint32_t tiling_mode = I915_TILING_X; - srandom(0xdeadbeef); - - fd = drm_open_any(); - - bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - //drm_intel_bufmgr_gem_enable_reuse(bufmgr); - devid = intel_get_drm_devid(fd); - batch = intel_batchbuffer_alloc(bufmgr, devid); - - /* overallocate the buffers we're actually using because */ - scratch_bo = drm_intel_bo_alloc_tiled(bufmgr, "scratch bo", 1024, - BO_SIZE/4096, 4, - &tiling_mode, &scratch_pitch, 0); - assert(tiling_mode == I915_TILING_X); - assert(scratch_pitch == 4096); - staging_bo = drm_intel_bo_alloc(bufmgr, "staging bo", BO_SIZE, 4096); - tiled_staging_bo = drm_intel_bo_alloc_tiled(bufmgr, "scratch bo", 1024, - BO_SIZE/4096, 4, - &tiling_mode, - &scratch_pitch, 0); - - drmtest_init_aperture_trashers(bufmgr); - mappable_gtt_limit = gem_mappable_aperture_size(); - - printf("checking partial reads\n"); for (i = 0; i < ROUNDS; i++) { int start, len; int val = i % 256; @@ -168,17 +142,19 @@ int main(int argc, char **argv) drm_intel_bo_get_subdata(scratch_bo, start, len, tmp); for (j = 0; j < len; j++) { - if (tmp[j] != val) { - printf("mismatch at %i, got: %i, expected: %i\n", - start + j, tmp[j], val); - exit(1); - } + igt_assert_f(tmp[j] == val, + "mismatch at %i, got: %i, expected: %i\n", + start + j, tmp[j], val); } - drmtest_progress("partial reads test: ", i, ROUNDS); + igt_progress("partial reads test: ", i, ROUNDS); } +} + +static void test_partial_writes(void) +{ + int i, j; - printf("checking partial writes\n"); for (i = 0; i < ROUNDS; i++) { int start, len; int val = i % 256; @@ -197,32 +173,30 @@ int main(int argc, char **argv) compare_tmp); for (j = 0; j < start; j++) { - if (compare_tmp[j] != val) { - printf("amismatch at %i, got: %i, expected: %i\n", - j, tmp[j], val); - exit(1); - } + igt_assert_f(compare_tmp[j] == val, + "mismatch at %i, got: %i, expected: %i\n", + j, tmp[j], val); } for (; j < start + len; j++) { - if (compare_tmp[j] != tmp[0]) { - printf("bmismatch at %i, got: %i, expected: %i\n", - j, tmp[j], i); - exit(1); - } + igt_assert_f(compare_tmp[j] == tmp[0], + "mismatch at %i, got: %i, expected: %i\n", + j, tmp[j], i); } for (; j < BO_SIZE; j++) { - if (compare_tmp[j] != val) { - printf("cmismatch at %i, got: %i, expected: %i\n", - j, tmp[j], val); - exit(1); - } + igt_assert_f(compare_tmp[j] == val, + "mismatch at %i, got: %i, expected: %i\n", + j, tmp[j], val); } drm_intel_gem_bo_unmap_gtt(staging_bo); - drmtest_progress("partial writes test: ", i, ROUNDS); + igt_progress("partial writes test: ", i, ROUNDS); } +} + +static void test_partial_read_writes(void) +{ + int i, j; - printf("checking partial writes after partial reads\n"); for (i = 0; i < ROUNDS; i++) { int start, len; int val = i % 256; @@ -235,11 +209,9 @@ int main(int argc, char **argv) drm_intel_bo_get_subdata(scratch_bo, start, len, tmp); for (j = 0; j < len; j++) { - if (tmp[j] != val) { - printf("mismatch in read at %i, got: %i, expected: %i\n", - start + j, tmp[j], val); - exit(1); - } + igt_assert_f(tmp[j] == val, + "mismatch in read at %i, got: %i, expected: %i\n", + start + j, tmp[j], val); } /* Change contents through gtt to make the pread cachelines @@ -260,35 +232,71 @@ int main(int argc, char **argv) compare_tmp); for (j = 0; j < start; j++) { - if (compare_tmp[j] != val) { - printf("mismatch at %i, got: %i, expected: %i\n", - j, tmp[j], val); - exit(1); - } + igt_assert_f(compare_tmp[j] == val, + "mismatch at %i, got: %i, expected: %i\n", + j, tmp[j], val); } for (; j < start + len; j++) { - if (compare_tmp[j] != tmp[0]) { - printf("mismatch at %i, got: %i, expected: %i\n", - j, tmp[j], tmp[0]); - exit(1); - } + igt_assert_f(compare_tmp[j] == tmp[0], + "mismatch at %i, got: %i, expected: %i\n", + j, tmp[j], tmp[0]); } for (; j < BO_SIZE; j++) { - if (compare_tmp[j] != val) { - printf("mismatch at %i, got: %i, expected: %i\n", - j, tmp[j], val); - exit(1); - } + igt_assert_f(compare_tmp[j] == val, + "mismatch at %i, got: %i, expected: %i\n", + j, tmp[j], val); } drm_intel_gem_bo_unmap_gtt(staging_bo); - drmtest_progress("partial read/writes test: ", i, ROUNDS); + igt_progress("partial read/writes test: ", i, ROUNDS); } +} - drmtest_cleanup_aperture_trashers(); - drm_intel_bufmgr_destroy(bufmgr); +igt_main +{ + uint32_t tiling_mode = I915_TILING_X; - close(fd); + igt_skip_on_simulation(); - return 0; + srandom(0xdeadbeef); + + igt_fixture { + fd = drm_open_any(); + + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + //drm_intel_bufmgr_gem_enable_reuse(bufmgr); + devid = intel_get_drm_devid(fd); + batch = intel_batchbuffer_alloc(bufmgr, devid); + + /* overallocate the buffers we're actually using because */ + scratch_bo = drm_intel_bo_alloc_tiled(bufmgr, "scratch bo", 1024, + BO_SIZE/4096, 4, + &tiling_mode, &scratch_pitch, 0); + igt_assert(tiling_mode == I915_TILING_X); + igt_assert(scratch_pitch == 4096); + staging_bo = drm_intel_bo_alloc(bufmgr, "staging bo", BO_SIZE, 4096); + tiled_staging_bo = drm_intel_bo_alloc_tiled(bufmgr, "scratch bo", 1024, + BO_SIZE/4096, 4, + &tiling_mode, + &scratch_pitch, 0); + + igt_init_aperture_trashers(bufmgr); + mappable_gtt_limit = gem_mappable_aperture_size(); + } + + igt_subtest("reads") + test_partial_reads(); + + igt_subtest("writes") + test_partial_writes(); + + igt_subtest("writes-after-reads") + test_partial_read_writes(); + + igt_fixture { + igt_cleanup_aperture_trashers(); + drm_intel_bufmgr_destroy(bufmgr); + + close(fd); + } } diff --git a/tests/gem_tiled_pread.c b/tests/gem_tiled_pread.c index 189affce..4815b724 100644 --- a/tests/gem_tiled_pread.c +++ b/tests/gem_tiled_pread.c @@ -38,18 +38,17 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include <sys/ioctl.h> -#include <sys/mman.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "intel_chipset.h" #define WIDTH 512 #define HEIGHT 512 @@ -71,7 +70,7 @@ gem_get_tiling(int fd, uint32_t handle, uint32_t *tiling, uint32_t *swizzle) get_tiling.handle = handle; ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling); - assert(ret == 0); + igt_assert(ret == 0); *tiling = get_tiling.tiling_mode; *swizzle = get_tiling.swizzle_mode; @@ -121,12 +120,11 @@ calculate_expected(int offset) int tile_y = tile_off / tile_width; int tile_x = (tile_off % tile_width) / 4; - /* printf("%3d, %3d, %3d,%3d\n", base_x, base_y, tile_x, tile_y); */ + igt_debug("%3d, %3d, %3d,%3d\n", base_x, base_y, tile_x, tile_y); return (base_y + tile_y) * WIDTH + base_x + tile_x; } -int -main(int argc, char **argv) +igt_simple_main { int fd; int i, iter = 100; @@ -213,25 +211,19 @@ main(int argc, char **argv) swizzle_str = "bit9^10^11"; break; default: - fprintf(stderr, "Bad swizzle bits; %d\n", - swizzle); - abort(); + igt_assert_f(0, "Bad swizzle bits; %d\n", + swizzle); } expected_val = calculate_expected(swizzled_offset); found_val = linear[(j - offset) / 4]; - if (expected_val != found_val) { - fprintf(stderr, - "Bad read [%d]: %d instead of %d at 0x%08x " - "for read from 0x%08x to 0x%08x, swizzle=%s\n", - i, found_val, expected_val, j, - offset, offset + len, - swizzle_str); - abort(); - } + igt_assert_f(expected_val == found_val, + "Bad read [%d]: %d instead of %d at 0x%08x " + "for read from 0x%08x to 0x%08x, swizzle=%s\n", + i, found_val, expected_val, j, + offset, offset + len, + swizzle_str); } } close(fd); - - return 0; } diff --git a/tests/gem_tiled_pread_pwrite.c b/tests/gem_tiled_pread_pwrite.c index e2225c5e..b6d9d627 100644 --- a/tests/gem_tiled_pread_pwrite.c +++ b/tests/gem_tiled_pread_pwrite.c @@ -47,18 +47,19 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include <sys/ioctl.h> -#include <sys/mman.h> -#include "drm.h" -#include "i915_drm.h" + +#include <drm.h> + +#include "ioctl_wrappers.h" #include "drmtest.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "igt_aux.h" #define WIDTH 512 #define HEIGHT 512 @@ -77,7 +78,7 @@ gem_get_tiling(int fd, uint32_t handle, uint32_t *tiling, uint32_t *swizzle) get_tiling.handle = handle; ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling); - assert(ret == 0); + igt_assert(ret == 0); *tiling = get_tiling.tiling_mode; *swizzle = get_tiling.swizzle_mode; @@ -113,8 +114,7 @@ create_bo(int fd) return handle; } -int -main(int argc, char **argv) +igt_simple_main { int fd; uint32_t *data; @@ -123,9 +123,8 @@ main(int argc, char **argv) uint32_t handle, handle_target; int count; - fd = drm_open_any(); - count = intel_get_total_ram_mb() * 9 / 10; + count = SLOW_QUICK(intel_get_total_ram_mb() * 9 / 10, 8) ; for (i = 0; i < count/2; i++) { current_tiling_mode = I915_TILING_X; @@ -141,19 +140,17 @@ main(int argc, char **argv) /* Check the target bo's contents. */ data = gem_mmap(fd, handle_target, sizeof(linear), PROT_READ | PROT_WRITE); for (j = 0; j < WIDTH*HEIGHT; j++) - if (data[j] != j) { - fprintf(stderr, "mismatch at %i: %i\n", - j, data[j]); - exit(1); - } + igt_assert_f(data[j] == j, + "mismatch at %i: %i\n", + j, data[j]); munmap(data, sizeof(linear)); /* Leak both bos so that we use all of system mem! */ + gem_madvise(fd, handle_target, I915_MADV_DONTNEED); + gem_madvise(fd, handle, I915_MADV_DONTNEED); - drmtest_progress("gem_tiled_pread_pwrite: ", i, count/2); + igt_progress("gem_tiled_pread_pwrite: ", i, count/2); } close(fd); - - return 0; } diff --git a/tests/gem_tiled_swapping.c b/tests/gem_tiled_swapping.c index d1484f0e..86c79f2d 100644 --- a/tests/gem_tiled_swapping.c +++ b/tests/gem_tiled_swapping.c @@ -47,22 +47,24 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include <sys/ioctl.h> -#include <sys/mman.h> -#include "drm.h" -#include "i915_drm.h" +#include <pthread.h> + +#include <drm.h> + +#include "ioctl_wrappers.h" #include "drmtest.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "igt_aux.h" #define WIDTH 512 #define HEIGHT 512 -static uint32_t linear[WIDTH * HEIGHT]; +#define LINEAR_DWORDS (4 * WIDTH * HEIGHT) static uint32_t current_tiling_mode; #define PAGE_SIZE 4096 @@ -74,72 +76,124 @@ create_bo_and_fill(int fd) uint32_t *data; int i; - handle = gem_create(fd, sizeof(linear)); + handle = gem_create(fd, LINEAR_DWORDS); gem_set_tiling(fd, handle, current_tiling_mode, WIDTH * sizeof(uint32_t)); /* Fill the BO with dwords starting at start_val */ - data = gem_mmap(fd, handle, sizeof(linear), PROT_READ | PROT_WRITE); + data = gem_mmap(fd, handle, LINEAR_DWORDS, PROT_READ | PROT_WRITE); + if (data == NULL && errno == ENOSPC) + return 0; + for (i = 0; i < WIDTH*HEIGHT; i++) data[i] = i; - munmap(data, sizeof(linear)); + munmap(data, LINEAR_DWORDS); return handle; } uint32_t *bo_handles; -int *idx_arr; -int -main(int argc, char **argv) +struct thread { + pthread_t thread; + int *idx_arr; + int fd, count; +}; + +static void +check_bo(int fd, uint32_t handle) { - int fd; uint32_t *data; - int i, j; - int count; - current_tiling_mode = I915_TILING_X; + int j; + + /* Check the target bo's contents. */ + data = gem_mmap(fd, handle, LINEAR_DWORDS, PROT_READ | PROT_WRITE); + for (j = 0; j < WIDTH*HEIGHT; j++) + igt_assert_f(data[j] == j, + "mismatch at %i: %i\n", + j, data[j]); + munmap(data, LINEAR_DWORDS); +} - fd = drm_open_any(); - /* need slightly more than total ram */ - count = intel_get_total_ram_mb() * 11 / 10; - bo_handles = calloc(count, sizeof(uint32_t)); - assert(bo_handles); +static void *thread_run(void *data) +{ + struct thread *t = data; + int i; - idx_arr = calloc(count, sizeof(int)); - assert(idx_arr); + for (i = 0; i < t->count; i++) + check_bo(t->fd, bo_handles[t->idx_arr[i]]); - if (intel_get_total_swap_mb() == 0) { - printf("no swap detected\n"); - return 77; - } + return NULL; +} - if (intel_get_total_ram_mb() / 4 > intel_get_total_swap_mb()) { - printf("not enough swap detected\n"); - return 77; - } +static void thread_init(struct thread *t, int fd, int count) +{ + int i; - for (i = 0; i < count; i++) - bo_handles[i] = create_bo_and_fill(fd); + t->fd = fd; + t->count = count; + t->idx_arr = calloc(count, sizeof(int)); + igt_assert(t->idx_arr); for (i = 0; i < count; i++) - idx_arr[i] = i; - - drmtest_permute_array(idx_arr, count, - drmtest_exchange_int); - - for (i = 0; i < count/2; i++) { - /* Check the target bo's contents. */ - data = gem_mmap(fd, bo_handles[idx_arr[i]], - sizeof(linear), PROT_READ | PROT_WRITE); - for (j = 0; j < WIDTH*HEIGHT; j++) - if (data[j] != j) { - fprintf(stderr, "mismatch at %i: %i\n", - j, data[j]); - exit(1); - } - munmap(data, sizeof(linear)); + t->idx_arr[i] = i; + + igt_permute_array(t->idx_arr, count, igt_exchange_int); +} + +static void thread_fini(struct thread *t) +{ + free(t->idx_arr); +} + +igt_simple_main +{ + struct thread *threads; + int fd, n, count, num_threads; + + current_tiling_mode = I915_TILING_X; + + igt_skip_on_simulation(); + intel_purge_vm_caches(); + + fd = drm_open_any(); + /* need slightly more than available memory */ + count = intel_get_total_ram_mb() + intel_get_total_swap_mb() / 4; + bo_handles = calloc(count, sizeof(uint32_t)); + igt_assert(bo_handles); + + num_threads = gem_available_fences(fd); + threads = calloc(num_threads, sizeof(struct thread)); + igt_assert(threads); + + igt_log(IGT_LOG_INFO, + "Using %d 1MiB objects (available RAM: %ld/%ld, swap: %ld)\n", + count, + (long)intel_get_avail_ram_mb(), + (long)intel_get_total_ram_mb(), + (long)intel_get_total_swap_mb()); + igt_require(intel_check_memory(count, 1024*1024, CHECK_RAM | CHECK_SWAP)); + + for (n = 0; n < count; n++) { + bo_handles[n] = create_bo_and_fill(fd); + /* Not enough mmap address space possible. */ + igt_require(bo_handles[n]); } - close(fd); + thread_init(&threads[0], fd, count); + thread_run(&threads[0]); + thread_fini(&threads[0]); + + /* Once more with threads */ + igt_subtest("threaded") { + for (n = 0; n < num_threads; n++) { + thread_init(&threads[n], fd, count); + pthread_create(&threads[n].thread, NULL, thread_run, &threads[n]); + } + for (n = 0; n < num_threads; n++) { + pthread_join(threads[n].thread, NULL); + thread_fini(&threads[n]); + } + } - return 0; + close(fd); } diff --git a/tests/gem_tiling_max_stride.c b/tests/gem_tiling_max_stride.c new file mode 100644 index 00000000..4d0553d4 --- /dev/null +++ b/tests/gem_tiling_max_stride.c @@ -0,0 +1,139 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Ville Syrjälä <ville.syrjala@linux.intel.com> + * + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <limits.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include "drm.h" +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_io.h" +#include "intel_chipset.h" + +static void do_test_invalid_tiling(int fd, uint32_t handle, int tiling, int stride) +{ + igt_assert(__gem_set_tiling(fd, handle, tiling, tiling ? stride : 0) == -EINVAL); +} + +static void test_invalid_tiling(int fd, uint32_t handle, int stride) +{ + do_test_invalid_tiling(fd, handle, I915_TILING_X, stride); + do_test_invalid_tiling(fd, handle, I915_TILING_Y, stride); +} + +/** + * Testcase: Check that max fence stride works + */ + +igt_simple_main +{ + int fd; + uint32_t *ptr; + uint32_t *data; + uint32_t handle; + uint32_t stride; + uint32_t size; + uint32_t devid; + int i = 0, x, y; + int tile_width = 512; + int tile_height = 8; + + fd = drm_open_any(); + + devid = intel_get_drm_devid(fd); + + if (intel_gen(devid) >= 7) + stride = 256 * 1024; + else if (intel_gen(devid) >= 4) + stride = 128 * 1024; + else { + if (IS_GEN2(devid)) { + tile_width = 128; + tile_height = 16; + } + stride = 8 * 1024; + } + + size = stride * tile_height; + + data = malloc(size); + igt_assert(data); + + /* Fill each line with the line number */ + for (y = 0; y < tile_height; y++) { + for (x = 0; x < stride / 4; x++) + data[i++] = y; + } + + handle = gem_create(fd, size); + + ptr = gem_mmap(fd, handle, size, PROT_READ | PROT_WRITE); + igt_assert(ptr); + + test_invalid_tiling(fd, handle, 0); + test_invalid_tiling(fd, handle, 64); + test_invalid_tiling(fd, handle, stride - 1); + test_invalid_tiling(fd, handle, stride + 1); + test_invalid_tiling(fd, handle, stride + 127); + test_invalid_tiling(fd, handle, stride + 128); + test_invalid_tiling(fd, handle, stride + tile_width - 1); + test_invalid_tiling(fd, handle, stride + tile_width); + test_invalid_tiling(fd, handle, stride * 2); + test_invalid_tiling(fd, handle, INT_MAX); + test_invalid_tiling(fd, handle, UINT_MAX); + + gem_set_tiling(fd, handle, I915_TILING_X, stride); + + gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); + + memcpy(ptr, data, size); + + gem_set_tiling(fd, handle, I915_TILING_NONE, 0); + + memcpy(data, ptr, size); + + /* Check that each tile contains the expected pattern */ + for (i = 0; i < size / 4; ) { + for (y = 0; y < tile_height; y++) { + for (x = 0; x < tile_width / 4; x++) { + igt_assert(y == data[i]); + i++; + } + } + } + + munmap(ptr, size); + + close(fd); +} diff --git a/tests/gem_unfence_active_buffers.c b/tests/gem_unfence_active_buffers.c index bffc62ea..aa0e01e1 100644 --- a/tests/gem_unfence_active_buffers.c +++ b/tests/gem_unfence_active_buffers.c @@ -41,7 +41,6 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> @@ -49,11 +48,12 @@ #include <sys/time.h> #include <stdbool.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "intel_chipset.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; @@ -64,12 +64,14 @@ uint32_t devid; uint32_t data[TEST_SIZE/4]; -int main(int argc, char **argv) +igt_simple_main { int i, ret, fd, num_fences; drm_intel_bo *busy_bo, *test_bo; uint32_t tiling = I915_TILING_X; + igt_skip_on_simulation(); + for (i = 0; i < 1024*256; i++) data[i] = i; @@ -80,23 +82,22 @@ int main(int argc, char **argv) devid = intel_get_drm_devid(fd); batch = intel_batchbuffer_alloc(bufmgr, devid); - printf("filling ring\n"); + igt_info("filling ring\n"); busy_bo = drm_intel_bo_alloc(bufmgr, "busy bo bo", 16*1024*1024, 4096); for (i = 0; i < 250; i++) { - BEGIN_BATCH(8); - OUT_BATCH(XY_SRC_COPY_BLT_CMD | - XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); + BLIT_COPY_BATCH_START(devid, 0); OUT_BATCH((3 << 24) | /* 32 bits */ (0xcc << 16) | /* copy ROP */ 2*1024*4); OUT_BATCH(0 << 16 | 1024); OUT_BATCH((2048) << 16 | (2048)); OUT_RELOC_FENCED(busy_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(devid); OUT_BATCH(0 << 16 | 0); OUT_BATCH(2*1024*4); OUT_RELOC_FENCED(busy_bo, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(devid); ADVANCE_BATCH(); if (IS_GEN6(devid) || IS_GEN7(devid)) { @@ -110,51 +111,49 @@ int main(int argc, char **argv) intel_batchbuffer_flush(batch); num_fences = gem_available_fences(fd); - printf("creating havoc on %i fences\n", num_fences); + igt_info("creating havoc on %i fences\n", num_fences); for (i = 0; i < num_fences*2; i++) { test_bo = drm_intel_bo_alloc(bufmgr, "test_bo", TEST_SIZE, 4096); ret = drm_intel_bo_set_tiling(test_bo, &tiling, TEST_STRIDE); - assert(ret == 0); + igt_assert(ret == 0); drm_intel_bo_disable_reuse(test_bo); - BEGIN_BATCH(8); - OUT_BATCH(XY_SRC_COPY_BLT_CMD | - XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); + BLIT_COPY_BATCH_START(devid, 0); OUT_BATCH((3 << 24) | /* 32 bits */ (0xcc << 16) | /* copy ROP */ TEST_STRIDE); OUT_BATCH(0 << 16 | 0); OUT_BATCH((1) << 16 | (1)); OUT_RELOC_FENCED(test_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(devid); OUT_BATCH(0 << 16 | 0); OUT_BATCH(TEST_STRIDE); OUT_RELOC_FENCED(test_bo, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(devid); ADVANCE_BATCH(); intel_batchbuffer_flush(batch); - printf("test bo offset: %#lx\n", test_bo->offset); + igt_info("test bo offset: %#lx\n", test_bo->offset); drm_intel_bo_unreference(test_bo); } /* launch a few batchs to ensure the damaged slab objects get reused. */ for (i = 0; i < 10; i++) { - BEGIN_BATCH(8); - OUT_BATCH(XY_SRC_COPY_BLT_CMD | - XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); + BLIT_COPY_BATCH_START(devid, 0); OUT_BATCH((3 << 24) | /* 32 bits */ (0xcc << 16) | /* copy ROP */ 2*1024*4); OUT_BATCH(0 << 16 | 1024); OUT_BATCH((1) << 16 | (1)); OUT_RELOC_FENCED(busy_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(devid); OUT_BATCH(0 << 16 | 0); OUT_BATCH(2*1024*4); OUT_RELOC_FENCED(busy_bo, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(devid); ADVANCE_BATCH(); if (IS_GEN6(devid) || IS_GEN7(devid)) { @@ -166,6 +165,4 @@ int main(int argc, char **argv) } } intel_batchbuffer_flush(batch); - - return 0; } diff --git a/tests/gem_unref_active_buffers.c b/tests/gem_unref_active_buffers.c index aa29c1de..cdc30990 100644 --- a/tests/gem_unref_active_buffers.c +++ b/tests/gem_unref_active_buffers.c @@ -35,62 +35,57 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "intel_bufmgr.h" #include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "intel_chipset.h" static drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; static drm_intel_bo *load_bo; -int main(int argc, char **argv) +igt_simple_main { int fd, i; + igt_skip_on_simulation(); + fd = drm_open_any(); bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - if (!bufmgr) { - fprintf(stderr, "failed to init libdrm\n"); - exit(-1); - } + igt_assert(bufmgr); /* don't enable buffer reuse!! */ //drm_intel_bufmgr_gem_enable_reuse(bufmgr); batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); - assert(batch); + igt_assert(batch); /* put some load onto the gpu to keep the light buffers active for long * enough */ for (i = 0; i < 1000; i++) { load_bo = drm_intel_bo_alloc(bufmgr, "target bo", 1024*4096, 4096); - if (!load_bo) { - fprintf(stderr, "failed to alloc target buffer\n"); - exit(-1); - } + igt_assert(load_bo); - BEGIN_BATCH(8); - OUT_BATCH(XY_SRC_COPY_BLT_CMD | - XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); + BLIT_COPY_BATCH_START(batch->devid, 0); OUT_BATCH((3 << 24) | /* 32 bits */ (0xcc << 16) | /* copy ROP */ 4096); OUT_BATCH(0); /* dst x1,y1 */ OUT_BATCH((1024 << 16) | 512); OUT_RELOC(load_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(batch->devid); OUT_BATCH((0 << 16) | 512); /* src x1, y1 */ OUT_BATCH(4096); OUT_RELOC(load_bo, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(batch->devid); ADVANCE_BATCH(); intel_batchbuffer_flush(batch); @@ -102,6 +97,4 @@ int main(int argc, char **argv) drm_intel_bufmgr_destroy(bufmgr); close(fd); - - return 0; } diff --git a/tests/gem_userptr_blits.c b/tests/gem_userptr_blits.c new file mode 100644 index 00000000..14efddae --- /dev/null +++ b/tests/gem_userptr_blits.c @@ -0,0 +1,1249 @@ +/* + * Copyright © 2009-2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * Chris Wilson <chris@chris-wilson.co.uk> + * Tvrtko Ursulin <tvrtko.ursulin@intel.com> + * + */ + +/** @file gem_userptr_blits.c + * + * This is a test of doing many blits using a mixture of normal system pages + * and uncached linear buffers, with a working set larger than the + * aperture size. + * + * The goal is to simply ensure the basics work. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <assert.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/mman.h> +#include <signal.h> + +#include "drm.h" +#include "i915_drm.h" + +#include "drmtest.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_chipset.h" +#include "ioctl_wrappers.h" + +#include "eviction_common.c" + +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif + +#define LOCAL_I915_GEM_USERPTR 0x33 +#define LOCAL_IOCTL_I915_GEM_USERPTR DRM_IOWR (DRM_COMMAND_BASE + LOCAL_I915_GEM_USERPTR, struct local_i915_gem_userptr) +struct local_i915_gem_userptr { + uint64_t user_ptr; + uint64_t user_size; + uint32_t flags; +#define LOCAL_I915_USERPTR_READ_ONLY (1<<0) +#define LOCAL_I915_USERPTR_UNSYNCHRONIZED (1<<31) + uint32_t handle; +}; + +static uint32_t userptr_flags = LOCAL_I915_USERPTR_UNSYNCHRONIZED; + +#define WIDTH 512 +#define HEIGHT 512 + +static uint32_t linear[WIDTH*HEIGHT]; + +static void gem_userptr_test_unsynchronized(void) +{ + userptr_flags = LOCAL_I915_USERPTR_UNSYNCHRONIZED; +} + +static void gem_userptr_test_synchronized(void) +{ + userptr_flags = 0; +} + +static int gem_userptr(int fd, void *ptr, int size, int read_only, uint32_t *handle) +{ + struct local_i915_gem_userptr userptr; + int ret; + + userptr.user_ptr = (uintptr_t)ptr; + userptr.user_size = size; + userptr.flags = userptr_flags; + if (read_only) + userptr.flags |= LOCAL_I915_USERPTR_READ_ONLY; + + ret = drmIoctl(fd, LOCAL_IOCTL_I915_GEM_USERPTR, &userptr); + if (ret) + ret = errno; + igt_skip_on_f(ret == ENODEV && + (userptr_flags & LOCAL_I915_USERPTR_UNSYNCHRONIZED) == 0 && + !read_only, + "Skipping, synchronized mappings with no kernel CONFIG_MMU_NOTIFIER?"); + if (ret == 0) + *handle = userptr.handle; + + return ret; +} + + +static void gem_userptr_sync(int fd, uint32_t handle) +{ + gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); +} + +static void +copy(int fd, uint32_t dst, uint32_t src, unsigned int error) +{ + uint32_t batch[12]; + struct drm_i915_gem_relocation_entry reloc[2]; + struct drm_i915_gem_exec_object2 obj[3]; + struct drm_i915_gem_execbuffer2 exec; + uint32_t handle; + int ret, i=0; + + batch[i++] = XY_SRC_COPY_BLT_CMD | + XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB; + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + batch[i - 1] |= 8; + else + batch[i - 1] |= 6; + + batch[i++] = (3 << 24) | /* 32 bits */ + (0xcc << 16) | /* copy ROP */ + WIDTH*4; + batch[i++] = 0; /* dst x1,y1 */ + batch[i++] = (HEIGHT << 16) | WIDTH; /* dst x2,y2 */ + batch[i++] = 0; /* dst reloc */ + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + batch[i++] = 0; + batch[i++] = 0; /* src x1,y1 */ + batch[i++] = WIDTH*4; + batch[i++] = 0; /* src reloc */ + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + batch[i++] = 0; + batch[i++] = MI_BATCH_BUFFER_END; + batch[i++] = MI_NOOP; + + handle = gem_create(fd, 4096); + gem_write(fd, handle, 0, batch, sizeof(batch)); + + reloc[0].target_handle = dst; + reloc[0].delta = 0; + reloc[0].offset = 4 * sizeof(batch[0]); + reloc[0].presumed_offset = 0; + reloc[0].read_domains = I915_GEM_DOMAIN_RENDER;; + reloc[0].write_domain = I915_GEM_DOMAIN_RENDER; + + reloc[1].target_handle = src; + reloc[1].delta = 0; + reloc[1].offset = 7 * sizeof(batch[0]); + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + reloc[1].offset += sizeof(batch[0]); + reloc[1].presumed_offset = 0; + reloc[1].read_domains = I915_GEM_DOMAIN_RENDER;; + reloc[1].write_domain = 0; + + obj[0].handle = dst; + obj[0].relocation_count = 0; + obj[0].relocs_ptr = 0; + obj[0].alignment = 0; + obj[0].offset = 0; + obj[0].flags = 0; + obj[0].rsvd1 = 0; + obj[0].rsvd2 = 0; + + obj[1].handle = src; + obj[1].relocation_count = 0; + obj[1].relocs_ptr = 0; + obj[1].alignment = 0; + obj[1].offset = 0; + obj[1].flags = 0; + obj[1].rsvd1 = 0; + obj[1].rsvd2 = 0; + + obj[2].handle = handle; + obj[2].relocation_count = 2; + obj[2].relocs_ptr = (uintptr_t)reloc; + obj[2].alignment = 0; + obj[2].offset = 0; + obj[2].flags = 0; + obj[2].rsvd1 = obj[2].rsvd2 = 0; + + exec.buffers_ptr = (uintptr_t)obj; + exec.buffer_count = 3; + exec.batch_start_offset = 0; + exec.batch_len = i * 4; + exec.DR1 = exec.DR4 = 0; + exec.num_cliprects = 0; + exec.cliprects_ptr = 0; + exec.flags = HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0; + i915_execbuffer2_set_context_id(exec, 0); + exec.rsvd2 = 0; + + ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); + if (ret) + ret = errno; + + if (error == ~0) + igt_assert(ret != 0); + else + igt_assert(ret == error); + + gem_close(fd, handle); +} + +static int +blit(int fd, uint32_t dst, uint32_t src, uint32_t *all_bo, int n_bo) +{ + uint32_t batch[12]; + struct drm_i915_gem_relocation_entry reloc[2]; + struct drm_i915_gem_exec_object2 *obj; + struct drm_i915_gem_execbuffer2 exec; + uint32_t handle; + int n, ret, i=0; + + batch[i++] = XY_SRC_COPY_BLT_CMD | + XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB; + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + batch[i - 1] |= 8; + else + batch[i - 1] |= 6; + batch[i++] = (3 << 24) | /* 32 bits */ + (0xcc << 16) | /* copy ROP */ + WIDTH*4; + batch[i++] = 0; /* dst x1,y1 */ + batch[i++] = (HEIGHT << 16) | WIDTH; /* dst x2,y2 */ + batch[i++] = 0; /* dst reloc */ + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + batch[i++] = 0; + batch[i++] = 0; /* src x1,y1 */ + batch[i++] = WIDTH*4; + batch[i++] = 0; /* src reloc */ + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + batch[i++] = 0; + batch[i++] = MI_BATCH_BUFFER_END; + batch[i++] = MI_NOOP; + + handle = gem_create(fd, 4096); + gem_write(fd, handle, 0, batch, sizeof(batch)); + + reloc[0].target_handle = dst; + reloc[0].delta = 0; + reloc[0].offset = 4 * sizeof(batch[0]); + reloc[0].presumed_offset = 0; + reloc[0].read_domains = I915_GEM_DOMAIN_RENDER; + reloc[0].write_domain = I915_GEM_DOMAIN_RENDER; + + reloc[1].target_handle = src; + reloc[1].delta = 0; + reloc[1].offset = 7 * sizeof(batch[0]); + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + reloc[1].offset += sizeof(batch[0]); + reloc[1].presumed_offset = 0; + reloc[1].read_domains = I915_GEM_DOMAIN_RENDER; + reloc[1].write_domain = 0; + + obj = calloc(n_bo + 1, sizeof(*obj)); + for (n = 0; n < n_bo; n++) + obj[n].handle = all_bo[n]; + obj[n].handle = handle; + obj[n].relocation_count = 2; + obj[n].relocs_ptr = (uintptr_t)reloc; + + exec.buffers_ptr = (uintptr_t)obj; + exec.buffer_count = n_bo + 1; + exec.batch_start_offset = 0; + exec.batch_len = i * 4; + exec.DR1 = exec.DR4 = 0; + exec.num_cliprects = 0; + exec.cliprects_ptr = 0; + exec.flags = HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0; + i915_execbuffer2_set_context_id(exec, 0); + exec.rsvd2 = 0; + + ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); + if (ret) + ret = errno; + + gem_close(fd, handle); + free(obj); + + return ret; +} + +static uint32_t +create_userptr(int fd, uint32_t val, uint32_t *ptr) +{ + uint32_t handle; + int i, ret; + + ret = gem_userptr(fd, ptr, sizeof(linear), 0, &handle); + igt_assert(ret == 0); + igt_assert(handle != 0); + + /* Fill the BO with dwords starting at val */ + for (i = 0; i < WIDTH*HEIGHT; i++) + ptr[i] = val++; + + return handle; +} + +static void **handle_ptr_map; +static unsigned int num_handle_ptr_map; + +static void add_handle_ptr(uint32_t handle, void *ptr) +{ + if (handle >= num_handle_ptr_map) { + handle_ptr_map = realloc(handle_ptr_map, + (handle + 1000) * sizeof(void*)); + num_handle_ptr_map = handle + 1000; + } + + handle_ptr_map[handle] = ptr; +} + +static void *get_handle_ptr(uint32_t handle) +{ + return handle_ptr_map[handle]; +} + +static void free_handle_ptr(uint32_t handle) +{ + igt_assert(handle < num_handle_ptr_map); + igt_assert(handle_ptr_map[handle]); + + free(handle_ptr_map[handle]); + handle_ptr_map[handle] = NULL; +} + +static uint32_t create_userptr_bo(int fd, int size) +{ + void *ptr; + uint32_t handle; + int ret; + + ret = posix_memalign(&ptr, PAGE_SIZE, size); + igt_assert(ret == 0); + + ret = gem_userptr(fd, (uint32_t *)ptr, size, 0, &handle); + igt_assert(ret == 0); + add_handle_ptr(handle, ptr); + + return handle; +} + +static void clear(int fd, uint32_t handle, int size) +{ + void *ptr = get_handle_ptr(handle); + + igt_assert(ptr != NULL); + + memset(ptr, 0, size); +} + +static void free_userptr_bo(int fd, uint32_t handle) +{ + gem_close(fd, handle); + free_handle_ptr(handle); +} + +static uint32_t +create_bo(int fd, uint32_t val) +{ + uint32_t handle; + int i; + + handle = gem_create(fd, sizeof(linear)); + + /* Fill the BO with dwords starting at val */ + for (i = 0; i < WIDTH*HEIGHT; i++) + linear[i] = val++; + gem_write(fd, handle, 0, linear, sizeof(linear)); + + return handle; +} + +static void +check_cpu(uint32_t *ptr, uint32_t val) +{ + int i; + + for (i = 0; i < WIDTH*HEIGHT; i++) { + igt_assert_f(ptr[i] == val, + "Expected 0x%08x, found 0x%08x " + "at offset 0x%08x\n", + val, ptr[i], i * 4); + val++; + } +} + +static void +check_gpu(int fd, uint32_t handle, uint32_t val) +{ + gem_read(fd, handle, 0, linear, sizeof(linear)); + check_cpu(linear, val); +} + +static int has_userptr(int fd) +{ + uint32_t handle = 0; + void *ptr; + uint32_t oldflags; + int ret; + + assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE) == 0); + oldflags = userptr_flags; + gem_userptr_test_unsynchronized(); + ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle); + userptr_flags = oldflags; + if (ret != 0) { + free(ptr); + return 0; + } + + gem_close(fd, handle); + free(ptr); + + return handle != 0; +} + +static int test_input_checking(int fd) +{ + struct local_i915_gem_userptr userptr; + int ret; + + /* Invalid flags. */ + userptr.user_ptr = 0; + userptr.user_size = 0; + userptr.flags = ~0; + ret = drmIoctl(fd, LOCAL_IOCTL_I915_GEM_USERPTR, &userptr); + igt_assert(ret != 0); + + /* Too big. */ + userptr.user_ptr = 0; + userptr.user_size = ~0; + userptr.flags = 0; + ret = drmIoctl(fd, LOCAL_IOCTL_I915_GEM_USERPTR, &userptr); + igt_assert(ret != 0); + + /* Both wrong. */ + userptr.user_ptr = 0; + userptr.user_size = ~0; + userptr.flags = ~0; + ret = drmIoctl(fd, LOCAL_IOCTL_I915_GEM_USERPTR, &userptr); + igt_assert(ret != 0); + + return 0; +} + +static int test_access_control(int fd) +{ + igt_fork(child, 1) { + void *ptr; + int ret; + uint32_t handle; + + igt_drop_root(); + + /* CAP_SYS_ADMIN is needed for UNSYNCHRONIZED mappings. */ + gem_userptr_test_unsynchronized(); + + igt_assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE) == 0); + + ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle); + if (ret == 0) + gem_close(fd, handle); + free(ptr); + igt_assert(ret == EPERM); + } + + igt_waitchildren(); + + return 0; +} + +static int test_invalid_mapping(int fd) +{ + int ret; + uint32_t handle, handle2; + void *ptr; + + /* NULL pointer. */ + ret = gem_userptr(fd, NULL, PAGE_SIZE, 0, &handle); + igt_assert(ret == 0); + copy(fd, handle, handle, ~0); /* QQQ Precise errno? */ + gem_close(fd, handle); + + /* GTT mapping */ + handle = create_bo(fd, 0); + ptr = gem_mmap__gtt(fd, handle, sizeof(linear), PROT_READ | PROT_WRITE); + if (ptr == NULL) + gem_close(fd, handle); + assert(ptr != NULL); + assert(((unsigned long)ptr & (PAGE_SIZE - 1)) == 0); + assert((sizeof(linear) & (PAGE_SIZE - 1)) == 0); + ret = gem_userptr(fd, ptr, sizeof(linear), 0, &handle2); + igt_assert(ret == 0); + copy(fd, handle, handle, ~0); /* QQQ Precise errno? */ + gem_close(fd, handle2); + munmap(ptr, sizeof(linear)); + gem_close(fd, handle); + + return 0; +} + +static int test_forbidden_ops(int fd) +{ + void *ptr; + int ret; + uint32_t handle; + char buf[PAGE_SIZE]; + struct drm_i915_gem_pread gem_pread; + struct drm_i915_gem_pwrite gem_pwrite; + + assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE) == 0); + + ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle); + igt_assert(ret == 0); + + gem_pread.handle = handle; + gem_pread.offset = 0; + gem_pread.size = PAGE_SIZE; + gem_pread.data_ptr = (uintptr_t)buf; + ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_PREAD, &gem_pread); + if (ret == 0) { + gem_close(fd, handle); + free(ptr); + } + igt_assert(ret != 0); + + gem_pwrite.handle = handle; + gem_pwrite.offset = 0; + gem_pwrite.size = PAGE_SIZE; + gem_pwrite.data_ptr = (uintptr_t)buf; + ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &gem_pwrite); + if (ret == 0) { + gem_close(fd, handle); + free(ptr); + } + igt_assert(ret != 0); + + gem_close(fd, handle); + free(ptr); + + return 0; +} + +static char counter; + +static void (*orig_sigbus)(int sig, siginfo_t *info, void *param); +static unsigned long sigbus_start; +static long sigbus_cnt = -1; + +static void +check_bo(int fd1, uint32_t handle1, int is_userptr, int fd2, uint32_t handle2) +{ + char *ptr1, *ptr2; + int i; + unsigned long size = sizeof(linear); + + if (is_userptr) + ptr1 = get_handle_ptr(handle1); + else + ptr1 = gem_mmap(fd1, handle1, sizeof(linear), PROT_READ | PROT_WRITE); + + ptr2 = gem_mmap(fd2, handle2, sizeof(linear), PROT_READ | PROT_WRITE); + + igt_assert(ptr1); + igt_assert(ptr2); + + sigbus_start = (unsigned long)ptr2; + + if (sigbus_cnt == 0) + size = 1; + + /* check whether it's still our old object first. */ + for (i = 0; i < size; i++) { + igt_assert(ptr1[i] == counter); + igt_assert(ptr2[i] == counter); + } + + counter++; + + if (size > 1) { + memset(ptr1, counter, size); + igt_assert(memcmp(ptr1, ptr2, size) == 0); + } + + if (!is_userptr) + munmap(ptr1, sizeof(linear)); + munmap(ptr2, sizeof(linear)); +} + +static int export_handle(int fd, uint32_t handle, int *outfd) +{ + struct drm_prime_handle args; + int ret; + + args.handle = handle; + args.flags = DRM_CLOEXEC; + args.fd = -1; + + ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args); + if (ret) + ret = errno; + *outfd = args.fd; + + return ret; +} + +static void sigbus(int sig, siginfo_t *info, void *param) +{ + unsigned long ptr = (unsigned long)info->si_addr; + void *addr; + + if (ptr >= sigbus_start && + ptr <= (sigbus_start + sizeof(linear))) { + sigbus_cnt++; + addr = mmap((void *)ptr, sizeof(linear), PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); + if ((unsigned long)addr == ptr) { + memset(addr, counter, sizeof(linear)); + return; + } + } + + if (orig_sigbus) + orig_sigbus(sig, info, param); + assert(0); +} + +static int test_dmabuf(void) +{ + int fd1, fd2; + uint32_t handle, handle_import1, handle_import2, handle_selfimport; + int dma_buf_fd = -1; + int ret; + struct sigaction sigact, orig_sigact; + + fd1 = drm_open_any(); + fd2 = drm_open_any(); + + handle = create_userptr_bo(fd1, sizeof(linear)); + + ret = export_handle(fd1, handle, &dma_buf_fd); + if (userptr_flags & LOCAL_I915_USERPTR_UNSYNCHRONIZED && ret) { + igt_assert(ret == EINVAL || ret == ENODEV); + free_userptr_bo(fd1, handle); + + return 0; + } else { + igt_assert(ret == 0); + igt_assert(dma_buf_fd >= 0); + } + handle_import1 = prime_fd_to_handle(fd2, dma_buf_fd); + check_bo(fd1, handle, 1, fd2, handle_import1); + + /* reimport should give us the same handle so that userspace can check + * whether it has that bo already somewhere. */ + handle_import2 = prime_fd_to_handle(fd2, dma_buf_fd); + igt_assert(handle_import1 == handle_import2); + + /* Same for re-importing on the exporting fd. */ + handle_selfimport = prime_fd_to_handle(fd1, dma_buf_fd); + igt_assert(handle == handle_selfimport); + + /* close dma_buf, check whether nothing disappears. */ + close(dma_buf_fd); + check_bo(fd1, handle, 1, fd2, handle_import1); + + /* destroy userptr object and expect SIGBUS */ + free_userptr_bo(fd1, handle); + sigact.sa_sigaction = sigbus; + sigact.sa_flags = SA_SIGINFO; + ret = sigaction(SIGBUS, &sigact, &orig_sigact); + assert(ret == 0); + orig_sigbus = orig_sigact.sa_sigaction; + sigbus_cnt = 0; + check_bo(fd2, handle_import1, 0, fd2, handle_import1); + assert(sigbus_cnt > 0); + sigact.sa_sigaction = orig_sigbus; + sigact.sa_flags = SA_SIGINFO; + ret = sigaction(SIGBUS, &sigact, &orig_sigact); + assert(ret == 0); + + gem_close(fd2, handle_import1); + close(fd1); + close(fd2); + + return 0; +} + +static int test_usage_restrictions(int fd) +{ + void *ptr; + int ret; + uint32_t handle; + + assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE * 2) == 0); + + /* Address not aligned. */ + ret = gem_userptr(fd, (char *)ptr + 1, PAGE_SIZE, 0, &handle); + igt_assert(ret != 0); + + /* Size not rounded to page size. */ + ret = gem_userptr(fd, ptr, PAGE_SIZE - 1, 0, &handle); + igt_assert(ret != 0); + + /* Both wrong. */ + ret = gem_userptr(fd, (char *)ptr + 1, PAGE_SIZE - 1, 0, &handle); + igt_assert(ret != 0); + + /* Read-only not supported. */ + ret = gem_userptr(fd, (char *)ptr, PAGE_SIZE, 1, &handle); + igt_assert(ret != 0); + + free(ptr); + + return 0; +} + +static int test_create_destroy(int fd) +{ + void *ptr; + int ret; + uint32_t handle; + + igt_assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE) == 0); + + ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle); + igt_assert(ret == 0); + + gem_close(fd, handle); + free(ptr); + + return 0; +} + +static int test_coherency(int fd, int count) +{ + uint32_t *memory; + uint32_t *cpu, *cpu_val; + uint32_t *gpu, *gpu_val; + uint32_t start = 0; + int i, ret; + + igt_info("Using 2x%d 1MiB buffers\n", count); + + ret = posix_memalign((void **)&memory, PAGE_SIZE, count*sizeof(linear)); + igt_assert(ret == 0 && memory); + + gpu = malloc(sizeof(uint32_t)*count*4); + gpu_val = gpu + count; + cpu = gpu_val + count; + cpu_val = cpu + count; + + for (i = 0; i < count; i++) { + gpu[i] = create_bo(fd, start); + gpu_val[i] = start; + start += WIDTH*HEIGHT; + } + + for (i = 0; i < count; i++) { + cpu[i] = create_userptr(fd, start, memory+i*WIDTH*HEIGHT); + cpu_val[i] = start; + start += WIDTH*HEIGHT; + } + + igt_info("Verifying initialisation...\n"); + for (i = 0; i < count; i++) { + check_gpu(fd, gpu[i], gpu_val[i]); + check_cpu(memory+i*WIDTH*HEIGHT, cpu_val[i]); + } + + igt_info("Cyclic blits cpu->gpu, forward...\n"); + for (i = 0; i < count * 4; i++) { + int src = i % count; + int dst = (i + 1) % count; + + copy(fd, gpu[dst], cpu[src], 0); + gpu_val[dst] = cpu_val[src]; + } + for (i = 0; i < count; i++) + check_gpu(fd, gpu[i], gpu_val[i]); + + igt_info("Cyclic blits gpu->cpu, backward...\n"); + for (i = 0; i < count * 4; i++) { + int src = (i + 1) % count; + int dst = i % count; + + copy(fd, cpu[dst], gpu[src], 0); + cpu_val[dst] = gpu_val[src]; + } + for (i = 0; i < count; i++) { + gem_userptr_sync(fd, cpu[i]); + check_cpu(memory+i*WIDTH*HEIGHT, cpu_val[i]); + } + + igt_info("Random blits...\n"); + for (i = 0; i < count * 4; i++) { + int src = random() % count; + int dst = random() % count; + + if (random() & 1) { + copy(fd, gpu[dst], cpu[src], 0); + gpu_val[dst] = cpu_val[src]; + } else { + copy(fd, cpu[dst], gpu[src], 0); + cpu_val[dst] = gpu_val[src]; + } + } + for (i = 0; i < count; i++) { + check_gpu(fd, gpu[i], gpu_val[i]); + gem_close(fd, gpu[i]); + + gem_userptr_sync(fd, cpu[i]); + check_cpu(memory+i*WIDTH*HEIGHT, cpu_val[i]); + gem_close(fd, cpu[i]); + } + + free(gpu); + free(memory); + + return 0; +} + +static struct igt_eviction_test_ops fault_ops = { + .create = create_userptr_bo, + .close = free_userptr_bo, + .copy = blit, + .clear = clear, +}; + +static int can_swap(void) +{ + unsigned long as, ram; + + /* Cannot swap if not enough address space */ + + /* FIXME: Improve check criteria. */ + if (sizeof(void*) < 8) + as = 3 * 1024; + else + as = 256 * 1024; /* Just a big number */ + + ram = intel_get_total_ram_mb(); + + if ((as - 128) < (ram - 256)) + return 0; + + return 1; +} + +#define min(a, b) ((a) < (b) ? (a) : (b)) + +static void test_forking_evictions(int fd, int size, int count, + unsigned flags) +{ + int trash_count; + int num_threads; + + trash_count = intel_get_total_ram_mb() * 11 / 10; + /* Use the fact test will spawn a number of child + * processes meaning swapping will be triggered system + * wide even if one process on it's own can't do it. + */ + num_threads = min(sysconf(_SC_NPROCESSORS_ONLN) * 4, 12); + trash_count /= num_threads; + if (count > trash_count) + count = trash_count; + + forking_evictions(fd, &fault_ops, size, count, trash_count, flags); +} + +static void test_swapping_evictions(int fd, int size, int count) +{ + int trash_count; + + igt_skip_on_f(!can_swap(), + "Not enough process address space for swapping tests.\n"); + + trash_count = intel_get_total_ram_mb() * 11 / 10; + + swapping_evictions(fd, &fault_ops, size, count, trash_count); +} + +static void test_minor_evictions(int fd, int size, int count) +{ + minor_evictions(fd, &fault_ops, size, count); +} + +static void test_major_evictions(int fd, int size, int count) +{ + major_evictions(fd, &fault_ops, size, count); +} + +static int test_overlap(int fd, int expected) +{ + char *ptr; + int ret; + uint32_t handle, handle2; + + igt_assert(posix_memalign((void *)&ptr, PAGE_SIZE, PAGE_SIZE * 3) == 0); + + ret = gem_userptr(fd, ptr + PAGE_SIZE, PAGE_SIZE, 0, &handle); + igt_assert(ret == 0); + + ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle2); + igt_assert(ret == 0); + gem_close(fd, handle2); + + ret = gem_userptr(fd, ptr + PAGE_SIZE * 2, PAGE_SIZE, 0, &handle2); + igt_assert(ret == 0); + gem_close(fd, handle2); + + ret = gem_userptr(fd, ptr, PAGE_SIZE * 2, 0, &handle2); + igt_assert(ret == expected); + if (ret == 0) + gem_close(fd, handle2); + + ret = gem_userptr(fd, ptr + PAGE_SIZE, PAGE_SIZE * 2, 0, &handle2); + igt_assert(ret == expected); + if (ret == 0) + gem_close(fd, handle2); + + ret = gem_userptr(fd, ptr, PAGE_SIZE * 3, 0, &handle2); + igt_assert(ret == expected); + if (ret == 0) + gem_close(fd, handle2); + + gem_close(fd, handle); + free(ptr); + + return 0; +} + +static int test_unmap(int fd, int expected) +{ + char *ptr, *bo_ptr; + const unsigned int num_obj = 3; + unsigned int i; + uint32_t bo[num_obj + 1]; + size_t map_size = sizeof(linear) * num_obj + (PAGE_SIZE - 1); + int ret; + + ptr = mmap(NULL, map_size, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + assert(ptr != MAP_FAILED); + + bo_ptr = (char *)ALIGN((unsigned long)ptr, PAGE_SIZE); + + for (i = 0; i < num_obj; i++, bo_ptr += sizeof(linear)) { + ret = gem_userptr(fd, bo_ptr, sizeof(linear), 0, &bo[i]); + igt_assert(ret == 0); + } + + bo[num_obj] = create_bo(fd, 0); + + for (i = 0; i < num_obj; i++) + copy(fd, bo[num_obj], bo[i], 0); + + ret = munmap(ptr, map_size); + assert(ret == 0); + + for (i = 0; i < num_obj; i++) + copy(fd, bo[num_obj], bo[i], expected); + + for (i = 0; i < (num_obj + 1); i++) + gem_close(fd, bo[i]); + + return 0; +} + +static int test_unmap_after_close(int fd) +{ + char *ptr, *bo_ptr; + const unsigned int num_obj = 3; + unsigned int i; + uint32_t bo[num_obj + 1]; + size_t map_size = sizeof(linear) * num_obj + (PAGE_SIZE - 1); + int ret; + + ptr = mmap(NULL, map_size, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + assert(ptr != MAP_FAILED); + + bo_ptr = (char *)ALIGN((unsigned long)ptr, PAGE_SIZE); + + for (i = 0; i < num_obj; i++, bo_ptr += sizeof(linear)) { + ret = gem_userptr(fd, bo_ptr, sizeof(linear), 0, &bo[i]); + igt_assert(ret == 0); + } + + bo[num_obj] = create_bo(fd, 0); + + for (i = 0; i < num_obj; i++) + copy(fd, bo[num_obj], bo[i], 0); + + for (i = 0; i < (num_obj + 1); i++) + gem_close(fd, bo[i]); + + ret = munmap(ptr, map_size); + assert(ret == 0); + + return 0; +} + +static int test_unmap_cycles(int fd, int expected) +{ + int i; + + for (i = 0; i < 1000; i++) + test_unmap(fd, expected); + + return 0; +} + +unsigned int total_ram; +uint64_t aperture_size; +int fd, count; + + +int main(int argc, char **argv) +{ + int size = sizeof(linear); + + igt_skip_on_simulation(); + + igt_subtest_init(argc, argv); + + igt_fixture { + int ret; + + fd = drm_open_any(); + igt_assert(fd >= 0); + + ret = has_userptr(fd); + igt_skip_on_f(ret == 0, "No userptr support - %s (%d)\n", + strerror(errno), ret); + + size = sizeof(linear); + + aperture_size = gem_aperture_size(fd); + igt_info("Aperture size is %lu MiB\n", (long)(aperture_size / (1024*1024))); + + if (argc > 1) + count = atoi(argv[1]); + if (count == 0) + count = 2 * aperture_size / (1024*1024) / 3; + + total_ram = intel_get_total_ram_mb(); + igt_info("Total RAM is %u MiB\n", total_ram); + + if (count > total_ram * 3 / 4) { + count = intel_get_total_ram_mb() * 3 / 4; + igt_info("Not enough RAM to run test, reducing buffer count.\n"); + } + } + + igt_subtest("input-checking") + test_input_checking(fd); + + igt_subtest("usage-restrictions") + test_usage_restrictions(fd); + + igt_subtest("invalid-mapping") + test_invalid_mapping(fd); + + igt_subtest("forbidden-operations") + test_forbidden_ops(fd); + + igt_info("Testing unsynchronized mappings...\n"); + gem_userptr_test_unsynchronized(); + + igt_subtest("create-destroy-unsync") + test_create_destroy(fd); + + igt_subtest("unsync-overlap") + test_overlap(fd, 0); + + igt_subtest("unsync-unmap") + test_unmap(fd, 0); + + igt_subtest("unsync-unmap-cycles") + test_unmap_cycles(fd, 0); + + igt_subtest("unsync-unmap-after-close") + test_unmap_after_close(fd); + + igt_subtest("coherency-unsync") + test_coherency(fd, count); + + igt_subtest("dmabuf-unsync") + test_dmabuf(); + + for (unsigned flags = 0; flags < ALL_FORKING_EVICTIONS + 1; flags++) { + igt_subtest_f("forked-unsync%s%s%s-%s", + flags & FORKING_EVICTIONS_SWAPPING ? "-swapping" : "", + flags & FORKING_EVICTIONS_DUP_DRMFD ? "-multifd" : "", + flags & FORKING_EVICTIONS_MEMORY_PRESSURE ? + "-mempressure" : "", + flags & FORKING_EVICTIONS_INTERRUPTIBLE ? + "interruptible" : "normal") { + test_forking_evictions(fd, size, count, flags); + } + } + + igt_subtest("swapping-unsync-normal") + test_swapping_evictions(fd, size, count); + + igt_subtest("minor-unsync-normal") + test_minor_evictions(fd, size, count); + + igt_subtest("major-unsync-normal") { + size = 200 * 1024 * 1024; + count = (gem_aperture_size(fd) / size) + 2; + test_major_evictions(fd, size, count); + } + + igt_fixture { + size = sizeof(linear); + count = 2 * gem_aperture_size(fd) / (1024*1024) / 3; + if (count > total_ram * 3 / 4) + count = intel_get_total_ram_mb() * 3 / 4; + } + + igt_fork_signal_helper(); + + igt_subtest("swapping-unsync-interruptible") + test_swapping_evictions(fd, size, count); + + igt_subtest("minor-unsync-interruptible") + test_minor_evictions(fd, size, count); + + igt_subtest("major-unsync-interruptible") { + size = 200 * 1024 * 1024; + count = (gem_aperture_size(fd) / size) + 2; + test_major_evictions(fd, size, count); + } + + igt_stop_signal_helper(); + + igt_info("Testing synchronized mappings...\n"); + + igt_fixture { + size = sizeof(linear); + count = 2 * gem_aperture_size(fd) / (1024*1024) / 3; + if (count > total_ram * 3 / 4) + count = intel_get_total_ram_mb() * 3 / 4; + } + + gem_userptr_test_synchronized(); + + igt_subtest("create-destroy-sync") + test_create_destroy(fd); + + igt_subtest("sync-overlap") + test_overlap(fd, EINVAL); + + igt_subtest("sync-unmap") + test_unmap(fd, EFAULT); + + igt_subtest("sync-unmap-cycles") + test_unmap_cycles(fd, EFAULT); + + igt_subtest("sync-unmap-after-close") + test_unmap_after_close(fd); + + igt_subtest("coherency-sync") + test_coherency(fd, count); + + igt_subtest("dmabuf-sync") + test_dmabuf(); + + for (unsigned flags = 0; flags < ALL_FORKING_EVICTIONS + 1; flags++) { + igt_subtest_f("forked-sync%s%s%s-%s", + flags & FORKING_EVICTIONS_SWAPPING ? "-swapping" : "", + flags & FORKING_EVICTIONS_DUP_DRMFD ? "-multifd" : "", + flags & FORKING_EVICTIONS_MEMORY_PRESSURE ? + "-mempressure" : "", + flags & FORKING_EVICTIONS_INTERRUPTIBLE ? + "interruptible" : "normal") { + test_forking_evictions(fd, size, count, flags); + } + } + + igt_subtest("swapping-normal-sync") + test_swapping_evictions(fd, size, count); + + igt_subtest("minor-normal-sync") + test_minor_evictions(fd, size, count); + + igt_subtest("major-normal-sync") { + size = 200 * 1024 * 1024; + count = (gem_aperture_size(fd) / size) + 2; + test_major_evictions(fd, size, count); + } + + igt_fixture { + size = 1024 * 1024; + count = 2 * gem_aperture_size(fd) / (1024*1024) / 3; + if (count > total_ram * 3 / 4) + count = intel_get_total_ram_mb() * 3 / 4; + } + + igt_fork_signal_helper(); + + igt_subtest("swapping-sync-interruptible") + test_swapping_evictions(fd, size, count); + + igt_subtest("minor-sync-interruptible") + test_minor_evictions(fd, size, count); + + igt_subtest("major-sync-interruptible") { + size = 200 * 1024 * 1024; + count = (gem_aperture_size(fd) / size) + 2; + test_major_evictions(fd, size, count); + } + + igt_stop_signal_helper(); + + igt_subtest("access-control") + test_access_control(fd); + + igt_exit(); + + return 0; +} diff --git a/tests/gem_vmap_blits.c b/tests/gem_vmap_blits.c deleted file mode 100644 index b8868214..00000000 --- a/tests/gem_vmap_blits.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright © 2009,2011 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * Authors: - * Eric Anholt <eric@anholt.net> - * Chris Wilson <chris@chris-wilson.co.uk> - * - */ - -/** @file gem_vmap_blits.c - * - * This is a test of doing many blits using a mixture of normal system pages - * and uncached linear buffers, with a working set larger than the - * aperture size. - * - * The goal is to simply ensure the basics work. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <assert.h> -#include <fcntl.h> -#include <inttypes.h> -#include <errno.h> -#include <sys/stat.h> -#include <sys/time.h> -#include "drm.h" -#include "i915_drm.h" -#include "drmtest.h" -#include "intel_bufmgr.h" -#include "intel_batchbuffer.h" -#include "intel_gpu_tools.h" - -#if !defined(I915_PARAM_HAS_VMAP) -#warning No vmap support in drm, skipping -int main(int argc, char **argv) -{ - fprintf(stderr, "No vmap support in drm.\n"); - return 77; -} -#else - -#define WIDTH 512 -#define HEIGHT 512 - -static uint32_t linear[WIDTH*HEIGHT]; - -static uint32_t gem_vmap(int fd, void *ptr, int size, int read_only) -{ - struct drm_i915_gem_vmap vmap; - - vmap.user_ptr = (uintptr_t)ptr; - vmap.user_size = size; - vmap.flags = 0; - if (read_only) - vmap.flags |= I915_VMAP_READ_ONLY; - - if (drmIoctl(fd, DRM_IOCTL_I915_GEM_VMAP, &vmap)) - return 0; - - return vmap.handle; -} - - -static void gem_vmap_sync(int fd, uint32_t handle) -{ - gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); -} - -static void -gem_read(int fd, uint32_t handle, int offset, int size, void *buf) -{ - struct drm_i915_gem_pread pread; - int ret; - - pread.handle = handle; - pread.offset = offset; - pread.size = size; - pread.data_ptr = (uintptr_t)buf; - ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_PREAD, &pread); - assert(ret == 0); -} - -static void -copy(int fd, uint32_t dst, uint32_t src) -{ - uint32_t batch[10]; - struct drm_i915_gem_relocation_entry reloc[2]; - struct drm_i915_gem_exec_object2 obj[3]; - struct drm_i915_gem_execbuffer2 exec; - uint32_t handle; - int ret; - - batch[0] = XY_SRC_COPY_BLT_CMD | - XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB; - batch[1] = (3 << 24) | /* 32 bits */ - (0xcc << 16) | /* copy ROP */ - WIDTH*4; - batch[2] = 0; /* dst x1,y1 */ - batch[3] = (HEIGHT << 16) | WIDTH; /* dst x2,y2 */ - batch[4] = 0; /* dst reloc */ - batch[5] = 0; /* src x1,y1 */ - batch[6] = WIDTH*4; - batch[7] = 0; /* src reloc */ - batch[8] = MI_BATCH_BUFFER_END; - batch[9] = MI_NOOP; - - handle = gem_create(fd, 4096); - gem_write(fd, handle, 0, batch, sizeof(batch)); - - reloc[0].target_handle = dst; - reloc[0].delta = 0; - reloc[0].offset = 4 * sizeof(batch[0]); - reloc[0].presumed_offset = 0; - reloc[0].read_domains = I915_GEM_DOMAIN_RENDER;; - reloc[0].write_domain = I915_GEM_DOMAIN_RENDER; - - reloc[1].target_handle = src; - reloc[1].delta = 0; - reloc[1].offset = 7 * sizeof(batch[0]); - reloc[1].presumed_offset = 0; - reloc[1].read_domains = I915_GEM_DOMAIN_RENDER;; - reloc[1].write_domain = 0; - - obj[0].handle = dst; - obj[0].relocation_count = 0; - obj[0].relocs_ptr = 0; - obj[0].alignment = 0; - obj[0].offset = 0; - obj[0].flags = 0; - obj[0].rsvd1 = 0; - obj[0].rsvd2 = 0; - - obj[1].handle = src; - obj[1].relocation_count = 0; - obj[1].relocs_ptr = 0; - obj[1].alignment = 0; - obj[1].offset = 0; - obj[1].flags = 0; - obj[1].rsvd1 = 0; - obj[1].rsvd2 = 0; - - obj[2].handle = handle; - obj[2].relocation_count = 2; - obj[2].relocs_ptr = (uintptr_t)reloc; - obj[2].alignment = 0; - obj[2].offset = 0; - obj[2].flags = 0; - obj[2].rsvd1 = obj[2].rsvd2 = 0; - - exec.buffers_ptr = (uintptr_t)obj; - exec.buffer_count = 3; - exec.batch_start_offset = 0; - exec.batch_len = sizeof(batch); - exec.DR1 = exec.DR4 = 0; - exec.num_cliprects = 0; - exec.cliprects_ptr = 0; - exec.flags = HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0; - exec.rsvd1 = exec.rsvd2 = 0; - - ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); - while (ret && errno == EBUSY) { - drmCommandNone(fd, DRM_I915_GEM_THROTTLE); - ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); - } - assert(ret == 0); - - gem_close(fd, handle); -} - -static uint32_t -create_vmap(int fd, uint32_t val, uint32_t *ptr) -{ - uint32_t handle; - int i; - - handle = gem_vmap(fd, ptr, sizeof(linear), 0); - - /* Fill the BO with dwords starting at val */ - for (i = 0; i < WIDTH*HEIGHT; i++) - ptr[i] = val++; - - return handle; -} - -static uint32_t -create_bo(int fd, uint32_t val) -{ - uint32_t handle; - int i; - - handle = gem_create(fd, sizeof(linear)); - - /* Fill the BO with dwords starting at val */ - for (i = 0; i < WIDTH*HEIGHT; i++) - linear[i] = val++; - gem_write(fd, handle, 0, linear, sizeof(linear)); - - return handle; -} - -static void -check_cpu(uint32_t *ptr, uint32_t val) -{ - int i; - - for (i = 0; i < WIDTH*HEIGHT; i++) { - if (ptr[i] != val) { - fprintf(stderr, "Expected 0x%08x, found 0x%08x " - "at offset 0x%08x\n", - val, ptr[i], i * 4); - abort(); - } - val++; - } -} - -static void -check_gpu(int fd, uint32_t handle, uint32_t val) -{ - gem_read(fd, handle, 0, linear, sizeof(linear)); - check_cpu(linear, val); -} - -static int has_vmap(int fd) -{ - drm_i915_getparam_t gp; - int i; - - gp.param = I915_PARAM_HAS_VMAP; - gp.value = &i; - - return drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp) == 0 && i > 0; -} - -int main(int argc, char **argv) -{ - uint32_t *memory; - uint32_t *cpu, *cpu_val; - uint32_t *gpu, *gpu_val; - uint32_t start = 0; - int i, fd, count; - - fd = drm_open_any(); - - if (!has_vmap(fd)) { - fprintf(stderr, "No vmap support, ignoring.\n"); - return 77; - } - - count = 0; - if (argc > 1) - count = atoi(argv[1]); - if (count == 0) - count = 3 * gem_aperture_size(fd) / (1024*1024) / 4; - printf("Using 2x%d 1MiB buffers\n", count); - - memory = malloc(count*sizeof(linear)); - if (memory == NULL) { - fprintf(stderr, "Unable to allocate %lld bytes\n", - (long long)count*sizeof(linear)); - return 1; - } - - gpu = malloc(sizeof(uint32_t)*count*4); - gpu_val = gpu + count; - cpu = gpu_val + count; - cpu_val = cpu + count; - - for (i = 0; i < count; i++) { - gpu[i] = create_bo(fd, start); - gpu_val[i] = start; - start += WIDTH*HEIGHT; - } - - for (i = 0; i < count; i++) { - cpu[i] = create_vmap(fd, start, memory+i*WIDTH*HEIGHT); - cpu_val[i] = start; - start += WIDTH*HEIGHT;; - } - - printf("Verifying initialisation...\n"); - for (i = 0; i < count; i++) { - check_gpu(fd, gpu[i], gpu_val[i]); - check_cpu(memory+i*WIDTH*HEIGHT, cpu_val[i]); - } - - printf("Cyclic blits cpu->gpu, forward...\n"); - for (i = 0; i < count * 4; i++) { - int src = i % count; - int dst = (i + 1) % count; - - copy(fd, gpu[dst], cpu[src]); - gpu_val[dst] = cpu_val[src]; - } - for (i = 0; i < count; i++) - check_gpu(fd, gpu[i], gpu_val[i]); - - printf("Cyclic blits gpu->cpu, backward...\n"); - for (i = 0; i < count * 4; i++) { - int src = (i + 1) % count; - int dst = i % count; - - copy(fd, cpu[dst], gpu[src]); - cpu_val[dst] = gpu_val[src]; - } - for (i = 0; i < count; i++) { - gem_vmap_sync(fd, cpu[i]); - check_cpu(memory+i*WIDTH*HEIGHT, cpu_val[i]); - } - - printf("Random blits...\n"); - for (i = 0; i < count * 4; i++) { - int src = random() % count; - int dst = random() % count; - - if (random() & 1) { - copy(fd, gpu[dst], cpu[src]); - gpu_val[dst] = cpu_val[src]; - } else { - copy(fd, cpu[dst], gpu[src]); - cpu_val[dst] = gpu_val[src]; - } - } - for (i = 0; i < count; i++) { - check_gpu(fd, gpu[i], gpu_val[i]); - gem_vmap_sync(fd, cpu[i]); - check_cpu(memory+i*WIDTH*HEIGHT, cpu_val[i]); - } - - return 0; -} - -#endif diff --git a/tests/gem_wait_render_timeout.c b/tests/gem_wait_render_timeout.c index c321d36c..a34c006c 100644 --- a/tests/gem_wait_render_timeout.c +++ b/tests/gem_wait_render_timeout.c @@ -27,8 +27,26 @@ #include <stdio.h> #include <time.h> -#include "drm.h" -#include "rendercopy.h" +#include <stdlib.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <getopt.h> + +#include <drm.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_io.h" +#include "intel_chipset.h" +#include "igt_aux.h" #define MSEC_PER_SEC 1000L #define USEC_PER_MSEC 1000L @@ -69,7 +87,7 @@ gem_bo_wait_timeout(int fd, uint32_t handle, uint64_t *timeout_ns) struct local_drm_i915_gem_wait wait; int ret; - assert(timeout_ns); + igt_assert(timeout_ns); wait.bo_handle = handle; wait.timeout_ns = *timeout_ns; @@ -80,38 +98,37 @@ gem_bo_wait_timeout(int fd, uint32_t handle, uint64_t *timeout_ns) return ret ? -errno : 0; } -static bool -gem_bo_busy(int fd, uint32_t handle) -{ - struct drm_i915_gem_busy busy; - - busy.handle = handle; - do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_BUSY, &busy)); - - return !!busy.busy; -} - static void blt_color_fill(struct intel_batchbuffer *batch, drm_intel_bo *buf, const unsigned int pages) { const unsigned short height = pages/4; const unsigned short width = 4096; - BEGIN_BATCH(5); - OUT_BATCH(COLOR_BLT_CMD | - COLOR_BLT_WRITE_ALPHA | - COLOR_BLT_WRITE_RGB); + + if (intel_gen(batch->devid) >= 8) { + BEGIN_BATCH(8); + OUT_BATCH(MI_NOOP); + OUT_BATCH(XY_COLOR_BLT_CMD_NOLEN | 5 | + COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB); + } else { + BEGIN_BATCH(6); + OUT_BATCH(XY_COLOR_BLT_CMD_NOLEN | 4 | + COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB); + } OUT_BATCH((3 << 24) | /* 32 Bit Color */ - 0xF0 | /* Raster OP copy background register */ + (0xF0 << 16) | /* Raster OP copy background register */ 0); /* Dest pitch is 0 */ + OUT_BATCH(0); OUT_BATCH(width << 16 | height); OUT_RELOC(buf, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + if (intel_gen(batch->devid) >= 8) + OUT_BATCH(0); OUT_BATCH(rand()); /* random pattern */ ADVANCE_BATCH(); } -int main(int argc, char **argv) +igt_simple_main { drm_intel_bufmgr *bufmgr; struct intel_batchbuffer *batch; @@ -122,6 +139,8 @@ int main(int argc, char **argv) bool done = false; int i, iter = 1; + igt_skip_on_simulation(); + fd = drm_open_any(); bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); @@ -131,10 +150,8 @@ int main(int argc, char **argv) dst = drm_intel_bo_alloc(bufmgr, "dst", BUF_SIZE, 4096); dst2 = drm_intel_bo_alloc(bufmgr, "dst2", BUF_SIZE, 4096); - if (gem_bo_wait_timeout(fd, dst->handle, &timeout) == -EINVAL) { - printf("kernel doesn't support wait_timeout, skipping test\n"); - return -77; - } + igt_skip_on_f(gem_bo_wait_timeout(fd, dst->handle, &timeout) == -EINVAL, + "kernel doesn't support wait_timeout, skipping test\n"); timeout = ENOUGH_WORK_IN_SECONDS * NSEC_PER_SEC; /* Figure out a rough number of fills required to consume 1 second of @@ -148,15 +165,15 @@ int main(int argc, char **argv) #define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC #endif - assert(clock_gettime(CLOCK_MONOTONIC_RAW, &start) == 0); + igt_assert(clock_gettime(CLOCK_MONOTONIC_RAW, &start) == 0); for (i = 0; i < iter; i++) blt_color_fill(batch, dst, BUF_PAGES); intel_batchbuffer_flush(batch); drm_intel_bo_wait_rendering(dst); - assert(clock_gettime(CLOCK_MONOTONIC_RAW, &end) == 0); + igt_assert(clock_gettime(CLOCK_MONOTONIC_RAW, &end) == 0); diff = do_time_diff(&end, &start); - assert(diff >= 0); + igt_assert(diff >= 0); if ((diff / MSEC_PER_SEC) > ENOUGH_WORK_IN_SECONDS) done = true; @@ -164,12 +181,12 @@ int main(int argc, char **argv) iter <<= 1; } while (!done && iter < 1000000); - assert(iter < 1000000); + igt_assert_cmpint(iter, <, 1000000); - printf("%d iters is enough work\n", iter); + igt_info("%d iters is enough work\n", iter); gem_quiescent_gpu(fd); if (do_signals) - drmtest_fork_signal_helper(); + igt_fork_signal_helper(); /* We should be able to do half as much work in the same amount of time, * but because we might schedule almost twice as much as required, we @@ -178,25 +195,21 @@ int main(int argc, char **argv) blt_color_fill(batch, dst2, BUF_PAGES); intel_batchbuffer_flush(batch); - assert(gem_bo_busy(fd, dst2->handle) == true); + igt_assert(gem_bo_busy(fd, dst2->handle) == true); - ret = gem_bo_wait_timeout(fd, dst2->handle, &timeout); - if (ret) { - fprintf(stderr, "Timed wait failed %s\n", strerror(errno)); - exit(EXIT_FAILURE); - } - assert(gem_bo_busy(fd, dst2->handle) == false); - assert(timeout != 0); + igt_assert(gem_bo_wait_timeout(fd, dst2->handle, &timeout) == 0); + igt_assert(gem_bo_busy(fd, dst2->handle) == false); + igt_assert_cmpint(timeout, !=, 0); if (timeout == (ENOUGH_WORK_IN_SECONDS * NSEC_PER_SEC)) - printf("Buffer was already done!\n"); + igt_info("Buffer was already done!\n"); else { - printf("Finished with %lu time remaining\n", timeout); + igt_info("Finished with %lu time remaining\n", timeout); } /* check that polling with timeout=0 works. */ timeout = 0; - assert(gem_bo_wait_timeout(fd, dst2->handle, &timeout) == 0); - assert(timeout == 0); + igt_assert(gem_bo_wait_timeout(fd, dst2->handle, &timeout) == 0); + igt_assert(timeout == 0); /* Now check that we correctly time out, twice the auto-tune load should * be good enough. */ @@ -207,24 +220,22 @@ int main(int argc, char **argv) intel_batchbuffer_flush(batch); ret = gem_bo_wait_timeout(fd, dst2->handle, &timeout); - assert(ret == -ETIME); - assert(timeout == 0); - assert(gem_bo_busy(fd, dst2->handle) == true); + igt_assert(ret == -ETIME); + igt_assert(timeout == 0); + igt_assert(gem_bo_busy(fd, dst2->handle) == true); /* check that polling with timeout=0 works. */ timeout = 0; - assert(gem_bo_wait_timeout(fd, dst2->handle, &timeout) == -ETIME); - assert(timeout == 0); + igt_assert(gem_bo_wait_timeout(fd, dst2->handle, &timeout) == -ETIME); + igt_assert(timeout == 0); if (do_signals) - drmtest_stop_signal_helper(); + igt_stop_signal_helper(); drm_intel_bo_unreference(dst2); drm_intel_bo_unreference(dst); intel_batchbuffer_free(batch); drm_intel_bufmgr_destroy(bufmgr); close(fd); - - return 0; } diff --git a/tests/gem_write_read_ring_switch.c b/tests/gem_write_read_ring_switch.c new file mode 100644 index 00000000..76e1c2af --- /dev/null +++ b/tests/gem_write_read_ring_switch.c @@ -0,0 +1,197 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Daniel Vetter <daniel.vetter@ffwll.ch> + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/time.h> + +#include <drm.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_chipset.h" +#include "intel_io.h" +#include "i830_reg.h" +#include "igt_aux.h" + +#define LOCAL_I915_EXEC_VEBOX (4<<0) + +static drm_intel_bufmgr *bufmgr; +struct intel_batchbuffer *batch; +static drm_intel_bo *load_bo, *target_bo, *dummy_bo; +int fd; + +/* Testcase: check read/write syncpoints when switching rings + * + * We've had a bug where the syncpoint for the last write was mangled after a + * ring switch using semaphores. This resulted in cpu reads returning before the + * write actually completed. This test exercises this. + */ + +#define COLOR 0xffffffff +static void run_test(int ring) +{ + uint32_t *ptr; + int i; + + gem_require_ring(fd, ring); + /* Testing render only makes sense with separate blt. */ + if (ring == I915_EXEC_RENDER) + gem_require_ring(fd, I915_EXEC_BLT); + + target_bo = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096); + igt_assert(target_bo); + + /* Need to map first so that we can do our own domain mangement with + * set_domain. */ + drm_intel_bo_map(target_bo, 0); + ptr = target_bo->virtual; + igt_assert(*ptr == 0); + + /* put some load onto the gpu to keep the light buffers active for long + * enough */ + for (i = 0; i < 1000; i++) { + BLIT_COPY_BATCH_START(batch->devid, 0); + OUT_BATCH((3 << 24) | /* 32 bits */ + (0xcc << 16) | /* copy ROP */ + 4096); + OUT_BATCH(0); /* dst x1,y1 */ + OUT_BATCH((1024 << 16) | 512); + OUT_RELOC(load_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(batch->devid); + OUT_BATCH((0 << 16) | 512); /* src x1, y1 */ + OUT_BATCH(4096); + OUT_RELOC(load_bo, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(batch->devid); + ADVANCE_BATCH(); + } + + COLOR_BLIT_COPY_BATCH_START(batch->devid, 0); + OUT_BATCH((3 << 24) | /* 32 bits */ + (0xff << 16) | + 128); + OUT_BATCH(0); /* dst x1,y1 */ + OUT_BATCH((1 << 16) | 1); + OUT_RELOC(target_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(batch->devid); + OUT_BATCH(COLOR); + ADVANCE_BATCH(); + + intel_batchbuffer_flush(batch); + + /* Emit an empty batch so that signalled seqno on the target ring > + * signalled seqnoe on the blt ring. This is required to hit the bug. */ + BEGIN_BATCH(2); + OUT_BATCH(MI_NOOP); + OUT_BATCH(MI_NOOP); + ADVANCE_BATCH(); + intel_batchbuffer_flush_on_ring(batch, ring); + + /* For the ring->ring sync it's important to only emit a read reloc, for + * otherwise the obj->last_write_seqno will be updated. */ + if (ring == I915_EXEC_RENDER) { + BEGIN_BATCH(4); + OUT_BATCH(MI_COND_BATCH_BUFFER_END | MI_DO_COMPARE); + OUT_BATCH(0xffffffff); /* compare dword */ + OUT_RELOC(target_bo, I915_GEM_DOMAIN_RENDER, 0, 0); + OUT_BATCH(MI_NOOP); + ADVANCE_BATCH(); + } else { + BEGIN_BATCH(4); + OUT_BATCH(MI_FLUSH_DW | 1); + OUT_BATCH(0); /* reserved */ + OUT_RELOC(target_bo, I915_GEM_DOMAIN_RENDER, 0, 0); + OUT_BATCH(MI_NOOP | (1<<22) | (0xf)); + ADVANCE_BATCH(); + } + intel_batchbuffer_flush_on_ring(batch, ring); + + gem_set_domain(fd, target_bo->handle, I915_GEM_DOMAIN_GTT, 0); + igt_assert(*ptr == COLOR); + drm_intel_bo_unmap(target_bo); + + drm_intel_bo_unreference(target_bo); +} + +igt_main +{ + static const struct { + const char *name; + int ring; + } tests[] = { + { "blt2render", I915_EXEC_RENDER }, + { "blt2bsd", I915_EXEC_BSD }, + { "blt2vebox", LOCAL_I915_EXEC_VEBOX }, + }; + int i; + + igt_skip_on_simulation(); + + igt_fixture { + fd = drm_open_any(); + + /* Test requires MI_FLUSH_DW and MI_COND_BATCH_BUFFER_END */ + igt_require(intel_gen(intel_get_drm_devid(fd)) >= 6); + + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); + igt_assert(bufmgr); + /* don't enable buffer reuse!! */ + //drm_intel_bufmgr_gem_enable_reuse(bufmgr); + + batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); + igt_assert(batch); + + dummy_bo = drm_intel_bo_alloc(bufmgr, "dummy bo", 4096, 4096); + igt_assert(dummy_bo); + + load_bo = drm_intel_bo_alloc(bufmgr, "load bo", 1024*4096, 4096); + igt_assert(load_bo); + } + + for (i = 0; i < ARRAY_SIZE(tests); i++) { + igt_subtest(tests[i].name) + run_test(tests[i].ring); + } + + igt_fork_signal_helper(); + for (i = 0; i < ARRAY_SIZE(tests); i++) { + igt_subtest_f("%s-interruptible", tests[i].name) + run_test(tests[i].ring); + } + igt_stop_signal_helper(); + + igt_fixture { + drm_intel_bufmgr_destroy(bufmgr); + + close(fd); + } +} diff --git a/tests/gen3_mixed_blits.c b/tests/gen3_mixed_blits.c index 5bb6d868..75d61a58 100644 --- a/tests/gen3_mixed_blits.c +++ b/tests/gen3_mixed_blits.c @@ -36,18 +36,17 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> -#include <sys/mman.h> #include <sys/ioctl.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "intel_chipset.h" #include "i915_reg.h" #include "i915_3d.h" @@ -268,11 +267,11 @@ render_copy(int fd, if ((b - batch) & 1) *b++ = 0; - assert(b - batch <= 1024); + igt_assert(b - batch <= 1024); handle = gem_create(fd, 4096); gem_write(fd, handle, 0, batch, (b-batch)*sizeof(batch[0])); - assert(r-reloc == 2); + igt_assert(r-reloc == 2); tiling_bits = 0; if (use_fence) @@ -320,7 +319,7 @@ render_copy(int fd, drmCommandNone(fd, DRM_I915_GEM_THROTTLE); ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); } - assert(ret == 0); + igt_assert(ret == 0); gem_close(fd, handle); } @@ -336,7 +335,7 @@ static void blt_copy(int fd, uint32_t dst, uint32_t src) *b++ = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); + XY_SRC_COPY_BLT_WRITE_RGB | 6); *b++ = 3 << 24 | 0xcc << 16 | WIDTH * 4; *b++ = 0; *b++ = HEIGHT << 16 | WIDTH; @@ -350,11 +349,11 @@ static void blt_copy(int fd, uint32_t dst, uint32_t src) if ((b - batch) & 1) *b++ = 0; - assert(b - batch <= 1024); + igt_assert(b - batch <= 1024); handle = gem_create(fd, 4096); gem_write(fd, handle, 0, batch, (b-batch)*sizeof(batch[0])); - assert(r-reloc == 2); + igt_assert(r-reloc == 2); obj[0].handle = dst; obj[0].relocation_count = 0; @@ -398,7 +397,7 @@ static void blt_copy(int fd, uint32_t dst, uint32_t src) drmCommandNone(fd, DRM_I915_GEM_THROTTLE); ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); } - assert(ret == 0); + igt_assert(ret == 0); gem_close(fd, handle); } @@ -432,7 +431,7 @@ create_bo(int fd, uint32_t val, int tiling) /* Fill the BO with dwords starting at val */ v = gem_mmap(fd, handle, WIDTH*HEIGHT*4, PROT_READ | PROT_WRITE); - assert(v); + igt_assert(v); for (i = 0; i < WIDTH*HEIGHT; i++) v[i] = val++; munmap(v, WIDTH*HEIGHT*4); @@ -447,14 +446,12 @@ check_bo(int fd, uint32_t handle, uint32_t val) int i; v = gem_mmap(fd, handle, WIDTH*HEIGHT*4, PROT_READ); - assert(v); + igt_assert(v); for (i = 0; i < WIDTH*HEIGHT; i++) { - if (v[i] != val) { - fprintf(stderr, "Expected 0x%08x, found 0x%08x " - "at offset 0x%08x\n", - val, v[i], i * 4); - abort(); - } + igt_assert_f(v[i] == val, + "Expected 0x%08x, found 0x%08x " + "at offset 0x%08x\n", + val, v[i], i * 4); val++; } munmap(v, WIDTH*HEIGHT*4); @@ -466,19 +463,18 @@ int main(int argc, char **argv) uint32_t start = 0; int i, fd, count; + igt_simple_init(); + fd = drm_open_any(); - if (!IS_GEN3(intel_get_drm_devid(fd))) { - printf("gen3-only test, doing nothing\n"); - return 77; - } + igt_require(IS_GEN3(intel_get_drm_devid(fd))); count = 0; if (argc > 1) count = atoi(argv[1]); if (count == 0) count = 3 * gem_aperture_size(fd) / (1024*1024) / 2; - printf("Using %d 1MiB buffers\n", count); + igt_info("Using %d 1MiB buffers\n", count); handle = malloc(sizeof(uint32_t)*count*3); tiling = handle + count; @@ -490,12 +486,12 @@ int main(int argc, char **argv) start += 1024 * 1024 / 4; } - printf("Verifying initialisation..."); fflush(stdout); + igt_info("Verifying initialisation..."); fflush(stdout); for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("done\n"); + igt_info("done\n"); - printf("Cyclic blits, forward..."); fflush(stdout); + igt_info("Cyclic blits, forward..."); fflush(stdout); for (i = 0; i < count * 32; i++) { int src = i % count; int dst = (i + 1) % count; @@ -503,12 +499,12 @@ int main(int argc, char **argv) copy(fd, handle[dst], tiling[dst], handle[src], tiling[src]); start_val[dst] = start_val[src]; } - printf("verifying..."); fflush(stdout); + igt_info("verifying..."); fflush(stdout); for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("done\n"); + igt_info("done\n"); - printf("Cyclic blits, backward..."); fflush(stdout); + igt_info("Cyclic blits, backward..."); fflush(stdout); for (i = 0; i < count * 32; i++) { int src = (i + 1) % count; int dst = i % count; @@ -516,12 +512,12 @@ int main(int argc, char **argv) copy(fd, handle[dst], tiling[dst], handle[src], tiling[src]); start_val[dst] = start_val[src]; } - printf("verifying..."); fflush(stdout); + igt_info("verifying..."); fflush(stdout); for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("done\n"); + igt_info("done\n"); - printf("Random blits..."); fflush(stdout); + igt_info("Random blits..."); fflush(stdout); for (i = 0; i < count * 32; i++) { int src = random() % count; int dst = random() % count; @@ -532,10 +528,10 @@ int main(int argc, char **argv) copy(fd, handle[dst], tiling[dst], handle[src], tiling[src]); start_val[dst] = start_val[src]; } - printf("verifying..."); fflush(stdout); + igt_info("verifying..."); fflush(stdout); for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("done\n"); + igt_info("done\n"); return 0; } diff --git a/tests/gen3_render_linear_blits.c b/tests/gen3_render_linear_blits.c index 529e23ff..7fe368d6 100644 --- a/tests/gen3_render_linear_blits.c +++ b/tests/gen3_render_linear_blits.c @@ -36,16 +36,16 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "intel_chipset.h" #include "i915_reg.h" #include "i915_3d.h" @@ -241,11 +241,11 @@ copy(int fd, uint32_t dst, uint32_t src) if ((b - batch) & 1) *b++ = 0; - assert(b - batch <= 1024); + igt_assert(b - batch <= 1024); handle = gem_create(fd, 4096); gem_write(fd, handle, 0, batch, (b-batch)*sizeof(batch[0])); - assert(r-reloc == 2); + igt_assert(r-reloc == 2); obj[0].handle = dst; obj[0].relocation_count = 0; @@ -289,7 +289,7 @@ copy(int fd, uint32_t dst, uint32_t src) drmCommandNone(fd, DRM_I915_GEM_THROTTLE); ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); } - assert(ret == 0); + igt_assert(ret == 0); gem_close(fd, handle); } @@ -317,12 +317,10 @@ check_bo(int fd, uint32_t handle, uint32_t val) gem_read(fd, handle, 0, linear, sizeof(linear)); for (i = 0; i < WIDTH*HEIGHT; i++) { - if (linear[i] != val) { - fprintf(stderr, "Expected 0x%08x, found 0x%08x " - "at offset 0x%08x\n", - val, linear[i], i * 4); - abort(); - } + igt_assert_f(linear[i] == val, + "Expected 0x%08x, found 0x%08x " + "at offset 0x%08x\n", + val, linear[i], i * 4); val++; } } @@ -333,19 +331,18 @@ int main(int argc, char **argv) uint32_t start = 0; int i, fd, count; + igt_simple_init(); + fd = drm_open_any(); - if (!IS_GEN3(intel_get_drm_devid(fd))) { - printf("gen3-only test, doing nothing\n"); - return 77; - } + igt_require(IS_GEN3(intel_get_drm_devid(fd))); count = 0; if (argc > 1) count = atoi(argv[1]); if (count == 0) count = 3 * gem_aperture_size(fd) / (1024*1024) / 2; - printf("Using %d 1MiB buffers\n", count); + igt_info("Using %d 1MiB buffers\n", count); handle = malloc(sizeof(uint32_t)*count*2); start_val = handle + count; @@ -356,11 +353,11 @@ int main(int argc, char **argv) start += 1024 * 1024 / 4; } - printf("Verifying initialisation...\n"); + igt_info("Verifying initialisation...\n"); for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("Cyclic blits, forward...\n"); + igt_info("Cyclic blits, forward...\n"); for (i = 0; i < count * 4; i++) { int src = i % count; int dst = (i + 1) % count; @@ -371,7 +368,7 @@ int main(int argc, char **argv) for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("Cyclic blits, backward...\n"); + igt_info("Cyclic blits, backward...\n"); for (i = 0; i < count * 4; i++) { int src = (i + 1) % count; int dst = i % count; @@ -382,7 +379,7 @@ int main(int argc, char **argv) for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("Random blits...\n"); + igt_info("Random blits...\n"); for (i = 0; i < count * 4; i++) { int src = random() % count; int dst = random() % count; diff --git a/tests/gen3_render_mixed_blits.c b/tests/gen3_render_mixed_blits.c index 1353b9d7..77ac0e2f 100644 --- a/tests/gen3_render_mixed_blits.c +++ b/tests/gen3_render_mixed_blits.c @@ -36,18 +36,17 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> -#include <sys/mman.h> #include <sys/ioctl.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "intel_chipset.h" #include "i915_reg.h" #include "i915_3d.h" @@ -255,11 +254,11 @@ copy(int fd, if ((b - batch) & 1) *b++ = 0; - assert(b - batch <= 1024); + igt_assert(b - batch <= 1024); handle = gem_create(fd, 4096); gem_write(fd, handle, 0, batch, (b-batch)*sizeof(batch[0])); - assert(r-reloc == 2); + igt_assert(r-reloc == 2); obj[0].handle = dst; obj[0].relocation_count = 0; @@ -303,7 +302,7 @@ copy(int fd, drmCommandNone(fd, DRM_I915_GEM_THROTTLE); ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); } - assert(ret == 0); + igt_assert(ret == 0); gem_close(fd, handle); } @@ -320,7 +319,7 @@ create_bo(int fd, uint32_t val, int tiling) /* Fill the BO with dwords starting at val */ v = gem_mmap(fd, handle, WIDTH*HEIGHT*4, PROT_READ | PROT_WRITE); - assert(v); + igt_assert(v); for (i = 0; i < WIDTH*HEIGHT; i++) v[i] = val++; munmap(v, WIDTH*HEIGHT*4); @@ -335,14 +334,12 @@ check_bo(int fd, uint32_t handle, uint32_t val) int i; v = gem_mmap(fd, handle, WIDTH*HEIGHT*4, PROT_READ); - assert(v); + igt_assert(v); for (i = 0; i < WIDTH*HEIGHT; i++) { - if (v[i] != val) { - fprintf(stderr, "Expected 0x%08x, found 0x%08x " - "at offset 0x%08x\n", - val, v[i], i * 4); - abort(); - } + igt_assert_f(v[i] == val, + "Expected 0x%08x, found 0x%08x " + "at offset 0x%08x\n", + val, v[i], i * 4); val++; } munmap(v, WIDTH*HEIGHT*4); @@ -354,19 +351,18 @@ int main(int argc, char **argv) uint32_t start = 0; int i, fd, count; + igt_simple_init(); + fd = drm_open_any(); - if (!IS_GEN3(intel_get_drm_devid(fd))) { - printf("gen3-only test, doing nothing\n"); - return 77; - } + igt_require(IS_GEN3(intel_get_drm_devid(fd))); count = 0; if (argc > 1) count = atoi(argv[1]); if (count == 0) count = 3 * gem_aperture_size(fd) / (1024*1024) / 2; - printf("Using %d 1MiB buffers\n", count); + igt_info("Using %d 1MiB buffers\n", count); handle = malloc(sizeof(uint32_t)*count*3); tiling = handle + count; @@ -378,12 +374,12 @@ int main(int argc, char **argv) start += 1024 * 1024 / 4; } - printf("Verifying initialisation..."); fflush(stdout); + igt_info("Verifying initialisation..."); fflush(stdout); for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("done\n"); + igt_info("done\n"); - printf("Cyclic blits, forward..."); fflush(stdout); + igt_info("Cyclic blits, forward..."); fflush(stdout); for (i = 0; i < count * 32; i++) { int src = i % count; int dst = (i + 1) % count; @@ -391,12 +387,12 @@ int main(int argc, char **argv) copy(fd, handle[dst], tiling[dst], handle[src], tiling[src]); start_val[dst] = start_val[src]; } - printf("verifying..."); fflush(stdout); + igt_info("verifying..."); fflush(stdout); for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("done\n"); + igt_info("done\n"); - printf("Cyclic blits, backward..."); fflush(stdout); + igt_info("Cyclic blits, backward..."); fflush(stdout); for (i = 0; i < count * 32; i++) { int src = (i + 1) % count; int dst = i % count; @@ -404,12 +400,12 @@ int main(int argc, char **argv) copy(fd, handle[dst], tiling[dst], handle[src], tiling[src]); start_val[dst] = start_val[src]; } - printf("verifying..."); fflush(stdout); + igt_info("verifying..."); fflush(stdout); for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("done\n"); + igt_info("done\n"); - printf("Random blits..."); fflush(stdout); + igt_info("Random blits..."); fflush(stdout); for (i = 0; i < count * 32; i++) { int src = random() % count; int dst = random() % count; @@ -420,10 +416,10 @@ int main(int argc, char **argv) copy(fd, handle[dst], tiling[dst], handle[src], tiling[src]); start_val[dst] = start_val[src]; } - printf("verifying..."); fflush(stdout); + igt_info("verifying..."); fflush(stdout); for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("done\n"); + igt_info("done\n"); return 0; } diff --git a/tests/gen3_render_tiledx_blits.c b/tests/gen3_render_tiledx_blits.c index 0e96e797..95c0c96b 100644 --- a/tests/gen3_render_tiledx_blits.c +++ b/tests/gen3_render_tiledx_blits.c @@ -36,18 +36,17 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> -#include <sys/mman.h> #include <sys/ioctl.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "intel_chipset.h" #include "i915_reg.h" #include "i915_3d.h" @@ -242,11 +241,11 @@ copy(int fd, uint32_t dst, uint32_t src) if ((b - batch) & 1) *b++ = 0; - assert(b - batch <= 1024); + igt_assert(b - batch <= 1024); handle = gem_create(fd, 4096); gem_write(fd, handle, 0, batch, (b-batch)*sizeof(batch[0])); - assert(r-reloc == 2); + igt_assert(r-reloc == 2); obj[0].handle = dst; obj[0].relocation_count = 0; @@ -290,7 +289,7 @@ copy(int fd, uint32_t dst, uint32_t src) drmCommandNone(fd, DRM_I915_GEM_THROTTLE); ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); } - assert(ret == 0); + igt_assert(ret == 0); gem_close(fd, handle); } @@ -307,7 +306,7 @@ create_bo(int fd, uint32_t val) /* Fill the BO with dwords starting at val */ v = gem_mmap(fd, handle, WIDTH*HEIGHT*4, PROT_READ | PROT_WRITE); - assert(v); + igt_assert(v); for (i = 0; i < WIDTH*HEIGHT; i++) v[i] = val++; munmap(v, WIDTH*HEIGHT*4); @@ -322,14 +321,12 @@ check_bo(int fd, uint32_t handle, uint32_t val) int i; v = gem_mmap(fd, handle, WIDTH*HEIGHT*4, PROT_READ); - assert(v); + igt_assert(v); for (i = 0; i < WIDTH*HEIGHT; i++) { - if (v[i] != val) { - fprintf(stderr, "Expected 0x%08x, found 0x%08x " - "at offset 0x%08x\n", - val, v[i], i * 4); - abort(); - } + igt_assert_f(v[i] == val, + "Expected 0x%08x, found 0x%08x " + "at offset 0x%08x\n", + val, v[i], i * 4); val++; } munmap(v, WIDTH*HEIGHT*4); @@ -341,19 +338,18 @@ int main(int argc, char **argv) uint32_t start = 0; int i, fd, count; + igt_simple_init(); + fd = drm_open_any(); - if (!IS_GEN3(intel_get_drm_devid(fd))) { - printf("gen3-only test, doing nothing\n"); - return 77; - } + igt_require(IS_GEN3(intel_get_drm_devid(fd))); count = 0; if (argc > 1) count = atoi(argv[1]); if (count == 0) count = 3 * gem_aperture_size(fd) / (1024*1024) / 2; - printf("Using %d 1MiB buffers\n", count); + igt_info("Using %d 1MiB buffers\n", count); handle = malloc(sizeof(uint32_t)*count*2); start_val = handle + count; @@ -364,11 +360,11 @@ int main(int argc, char **argv) start += 1024 * 1024 / 4; } - printf("Verifying initialisation...\n"); + igt_info("Verifying initialisation...\n"); for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("Cyclic blits, forward...\n"); + igt_info("Cyclic blits, forward...\n"); for (i = 0; i < count * 4; i++) { int src = i % count; int dst = (i + 1) % count; @@ -379,7 +375,7 @@ int main(int argc, char **argv) for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("Cyclic blits, backward...\n"); + igt_info("Cyclic blits, backward...\n"); for (i = 0; i < count * 4; i++) { int src = (i + 1) % count; int dst = i % count; @@ -390,7 +386,7 @@ int main(int argc, char **argv) for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("Random blits...\n"); + igt_info("Random blits...\n"); for (i = 0; i < count * 4; i++) { int src = random() % count; int dst = random() % count; diff --git a/tests/gen3_render_tiledy_blits.c b/tests/gen3_render_tiledy_blits.c index 90fc7eb9..1b9a4196 100644 --- a/tests/gen3_render_tiledy_blits.c +++ b/tests/gen3_render_tiledy_blits.c @@ -36,18 +36,17 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <sys/time.h> -#include <sys/mman.h> #include <sys/ioctl.h> #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" +#include "intel_chipset.h" #include "i915_reg.h" #include "i915_3d.h" @@ -242,11 +241,11 @@ copy(int fd, uint32_t dst, uint32_t src) if ((b - batch) & 1) *b++ = 0; - assert(b - batch <= 1024); + igt_assert(b - batch <= 1024); handle = gem_create(fd, 4096); gem_write(fd, handle, 0, batch, (b-batch)*sizeof(batch[0])); - assert(r-reloc == 2); + igt_assert(r-reloc == 2); obj[0].handle = dst; obj[0].relocation_count = 0; @@ -290,7 +289,7 @@ copy(int fd, uint32_t dst, uint32_t src) drmCommandNone(fd, DRM_I915_GEM_THROTTLE); ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); } - assert(ret == 0); + igt_assert(ret == 0); gem_close(fd, handle); } @@ -307,7 +306,7 @@ create_bo(int fd, uint32_t val) /* Fill the BO with dwords starting at val */ v = gem_mmap(fd, handle, WIDTH*HEIGHT*4, PROT_READ | PROT_WRITE); - assert(v); + igt_assert(v); for (i = 0; i < WIDTH*HEIGHT; i++) v[i] = val++; munmap(v, WIDTH*HEIGHT*4); @@ -322,14 +321,12 @@ check_bo(int fd, uint32_t handle, uint32_t val) int i; v = gem_mmap(fd, handle, WIDTH*HEIGHT*4, PROT_READ); - assert(v); + igt_assert(v); for (i = 0; i < WIDTH*HEIGHT; i++) { - if (v[i] != val) { - fprintf(stderr, "Expected 0x%08x, found 0x%08x " - "at offset 0x%08x\n", - val, v[i], i * 4); - abort(); - } + igt_assert_f(v[i] == val, + "Expected 0x%08x, found 0x%08x " + "at offset 0x%08x\n", + val, v[i], i * 4); val++; } munmap(v, WIDTH*HEIGHT*4); @@ -341,19 +338,18 @@ int main(int argc, char **argv) uint32_t start = 0; int i, fd, count; + igt_simple_init(); + fd = drm_open_any(); - if (!IS_GEN3(intel_get_drm_devid(fd))) { - printf("gen3-only test, doing nothing\n"); - return 77; - } + igt_require(IS_GEN3(intel_get_drm_devid(fd))); count = 0; if (argc > 1) count = atoi(argv[1]); if (count == 0) count = 3 * gem_aperture_size(fd) / (1024*1024) / 2; - printf("Using %d 1MiB buffers\n", count); + igt_info("Using %d 1MiB buffers\n", count); handle = malloc(sizeof(uint32_t)*count*2); start_val = handle + count; @@ -364,12 +360,12 @@ int main(int argc, char **argv) start += 1024 * 1024 / 4; } - printf("Verifying initialisation..."); fflush(stdout); + igt_info("Verifying initialisation..."); fflush(stdout); for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("done\n"); + igt_info("done\n"); - printf("Cyclic blits, forward..."); fflush(stdout); + igt_info("Cyclic blits, forward..."); fflush(stdout); for (i = 0; i < count * 32; i++) { int src = i % count; int dst = (i + 1) % count; @@ -377,12 +373,12 @@ int main(int argc, char **argv) copy(fd, handle[dst], handle[src]); start_val[dst] = start_val[src]; } - printf("verifying..."); fflush(stdout); + igt_info("verifying..."); fflush(stdout); for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("done\n"); + igt_info("done\n"); - printf("Cyclic blits, backward..."); fflush(stdout); + igt_info("Cyclic blits, backward..."); fflush(stdout); for (i = 0; i < count * 32; i++) { int src = (i + 1) % count; int dst = i % count; @@ -390,12 +386,12 @@ int main(int argc, char **argv) copy(fd, handle[dst], handle[src]); start_val[dst] = start_val[src]; } - printf("verifying..."); fflush(stdout); + igt_info("verifying..."); fflush(stdout); for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("done\n"); + igt_info("done\n"); - printf("Random blits..."); fflush(stdout); + igt_info("Random blits..."); fflush(stdout); for (i = 0; i < count * 32; i++) { int src = random() % count; int dst = random() % count; @@ -406,10 +402,10 @@ int main(int argc, char **argv) copy(fd, handle[dst], handle[src]); start_val[dst] = start_val[src]; } - printf("verifying..."); fflush(stdout); + igt_info("verifying..."); fflush(stdout); for (i = 0; i < count; i++) check_bo(fd, handle[i], start_val[i]); - printf("done\n"); + igt_info("done\n"); return 0; } diff --git a/tests/gen7_forcewake_mt.c b/tests/gen7_forcewake_mt.c new file mode 100644 index 00000000..0ea7d094 --- /dev/null +++ b/tests/gen7_forcewake_mt.c @@ -0,0 +1,206 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Chris Wilson <chris@chris-wilson.co.uk> + * + */ + +/* + * Testcase: Exercise a suspect workaround required for FORCEWAKE_MT + * + */ + +#include <sys/types.h> +#include <pthread.h> +#include <string.h> + +#include "drm.h" +#include "ioctl_wrappers.h" +#include "i915_pciids.h" +#include "drmtest.h" +#include "intel_io.h" +#include "intel_chipset.h" + +#define FORCEWAKE_MT 0xa188 + +struct thread { + pthread_t thread; + void *mmio; + int fd; + int bit; +}; + +static const struct pci_id_match match[] = { + INTEL_IVB_D_IDS(NULL), + INTEL_IVB_M_IDS(NULL), + + INTEL_HSW_D_IDS(NULL), + INTEL_HSW_M_IDS(NULL), + + { 0, 0, 0 }, +}; + +static struct pci_device *__igfx_get(void) +{ + struct pci_device *dev; + + if (pci_system_init()) + return 0; + + dev = pci_device_find_by_slot(0, 0, 2, 0); + if (dev == NULL || dev->vendor_id != 0x8086) { + struct pci_device_iterator *iter; + + iter = pci_id_match_iterator_create(match); + if (!iter) + return 0; + + dev = pci_device_next(iter); + pci_iterator_destroy(iter); + } + + return dev; +} + +static void *igfx_get_mmio(void) +{ + struct pci_device *pci = __igfx_get(); + int error; + + igt_skip_on(pci == NULL); + igt_skip_on(intel_gen(pci->device_id) != 7); + + error = pci_device_probe(pci); + igt_assert(error == 0); + + error = pci_device_map_range(pci, + pci->regions[0].base_addr, + 2*1024*1024, + PCI_DEV_MAP_FLAG_WRITABLE, + &mmio); + igt_assert(error == 0); + igt_assert(mmio != NULL); + + return mmio; +} + +static void *thread(void *arg) +{ + struct thread *t = arg; + uint32_t *forcewake_mt = (uint32_t *)((char *)t->mmio + FORCEWAKE_MT); + uint32_t bit = 1 << t->bit; + + while (1) { + *forcewake_mt = bit << 16 | bit; + igt_assert(*forcewake_mt & bit); + *forcewake_mt = bit << 16; + igt_assert((*forcewake_mt & bit) == 0); + } + + return NULL; +} + +#define MI_LOAD_REGISTER_IMM (0x22<<23) +#define MI_STORE_REGISTER_MEM (0x24<<23) + +igt_simple_main +{ + struct thread t[16]; + int i; + + t[0].fd = drm_open_any(); + t[0].mmio = igfx_get_mmio(); + + for (i = 2; i < 16; i++) { + t[i] = t[0]; + t[i].bit = i; + pthread_create(&t[i].thread, NULL, thread, &t[i]); + } + + sleep(2); + + for (i = 0; i < 1000; i++) { + uint32_t *p; + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 exec[2]; + struct drm_i915_gem_relocation_entry reloc[2]; + uint32_t b[] = { + MI_LOAD_REGISTER_IMM | 1, + FORCEWAKE_MT, + 2 << 16 | 2, + MI_STORE_REGISTER_MEM | 1, + FORCEWAKE_MT, + 0, // to be patched + MI_LOAD_REGISTER_IMM | 1, + FORCEWAKE_MT, + 2 << 16, + MI_STORE_REGISTER_MEM | 1, + FORCEWAKE_MT, + 1 * sizeof(uint32_t), // to be patched + MI_BATCH_BUFFER_END, + 0 + }; + + memset(exec, 0, sizeof(exec)); + exec[1].handle = gem_create(t[0].fd, 4096); + exec[1].relocation_count = 2; + exec[1].relocs_ptr = (uintptr_t)reloc; + gem_write(t[0].fd, exec[1].handle, 0, b, sizeof(b)); + exec[0].handle = gem_create(t[0].fd, 4096); + + reloc[0].offset = 5 * sizeof(uint32_t); + reloc[0].delta = 0; + reloc[0].target_handle = exec[0].handle; + reloc[0].read_domains = I915_GEM_DOMAIN_RENDER; + reloc[0].write_domain = I915_GEM_DOMAIN_RENDER; + reloc[0].presumed_offset = 0; + + reloc[1].offset = 11 * sizeof(uint32_t); + reloc[1].delta = 1 * sizeof(uint32_t); + reloc[1].target_handle = exec[0].handle; + reloc[1].read_domains = I915_GEM_DOMAIN_RENDER; + reloc[1].write_domain = I915_GEM_DOMAIN_RENDER; + reloc[1].presumed_offset = 0; + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = (uintptr_t)&exec; + execbuf.buffer_count = 2; + execbuf.batch_len = sizeof(b); + execbuf.flags = I915_EXEC_SECURE; + + gem_execbuf(t[0].fd, &execbuf); + gem_sync(t[0].fd, exec[1].handle); + + p = gem_mmap(t[0].fd, exec[0].handle, 4096, PROT_READ); + + igt_info("[%d]={ %08x %08x }\n", i, p[0], p[1]); + igt_assert(p[0] & 2); + igt_assert((p[1] & 2) == 0); + + munmap(p, 4096); + gem_close(t[0].fd, exec[0].handle); + gem_close(t[0].fd, exec[1].handle); + + usleep(1000); + } +} diff --git a/tests/igt_fork_helper.c b/tests/igt_fork_helper.c new file mode 100644 index 00000000..b4cf27eb --- /dev/null +++ b/tests/igt_fork_helper.c @@ -0,0 +1,37 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Daniel Vetter <daniel.vetter@ffwll.ch> + * + */ + +#include "drmtest.h" +#include "igt_aux.h" + +int main(int argc, char **argv) +{ + for (int i = 0; i < 1000; i++) { + igt_fork_signal_helper(); + igt_stop_signal_helper(); + } +} diff --git a/tests/igt_list_only.c b/tests/igt_list_only.c new file mode 100644 index 00000000..d3ea8c27 --- /dev/null +++ b/tests/igt_list_only.c @@ -0,0 +1,42 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Daniel Vetter <daniel.vetter@ffwll.ch> + * + */ + +#include "drmtest.h" + +int main(int argc, char **argv) +{ + char prog[] = "igt_list_only"; + char arg[] = "--list-subtests"; + char *fake_argv[] = {prog, arg}; + + igt_subtest_init(2, fake_argv); + + igt_subtest("A") + ; + + igt_exit(); +} diff --git a/tests/igt_no_exit.c b/tests/igt_no_exit.c new file mode 100644 index 00000000..ba3fae0a --- /dev/null +++ b/tests/igt_no_exit.c @@ -0,0 +1,39 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Daniel Vetter <daniel.vetter@ffwll.ch> + * + */ + +#include "drmtest.h" + +int main(int argc, char **argv) +{ + char prog[] = "igt_no_exit"; + char *fake_argv[] = {prog}; + + igt_subtest_init(1, fake_argv); + + igt_subtest("A") + ; +} diff --git a/tests/igt_no_exit_list_only.c b/tests/igt_no_exit_list_only.c new file mode 100644 index 00000000..3b232be7 --- /dev/null +++ b/tests/igt_no_exit_list_only.c @@ -0,0 +1,40 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Daniel Vetter <daniel.vetter@ffwll.ch> + * + */ + +#include "drmtest.h" + +int main(int argc, char **argv) +{ + char prog[] = "igt_list_only"; + char arg[] = "--list-subtests"; + char *fake_argv[] = {prog, arg}; + + igt_subtest_init(2, fake_argv); + + igt_subtest("A") + ; +} diff --git a/tests/igt_no_subtest.c b/tests/igt_no_subtest.c new file mode 100644 index 00000000..47f15fce --- /dev/null +++ b/tests/igt_no_subtest.c @@ -0,0 +1,38 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Daniel Vetter <daniel.vetter@ffwll.ch> + * + */ + +#include "drmtest.h" + +int main(int argc, char **argv) +{ + char prog[] = "igt_no_exit"; + char *fake_argv[] = {prog}; + + igt_subtest_init(1, fake_argv); + + igt_exit(); +} diff --git a/tests/igt_simulation.c b/tests/igt_simulation.c new file mode 100644 index 00000000..15cbe642 --- /dev/null +++ b/tests/igt_simulation.c @@ -0,0 +1,156 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Daniel Vetter <daniel.vetter@ffwll.ch> + * + */ + +#include <stdlib.h> +#include <sys/wait.h> +#include <sys/types.h> +#include <assert.h> +#include <errno.h> + +#include "drmtest.h" +#include "igt_core.h" + +bool simple; +bool list_subtests; +bool in_fixture; +bool in_subtest; + +char test[] = "test"; +char list[] = "--list-subtests"; +char *argv_list[] = { test, list }; +char *argv_run[] = { test }; + +static int do_fork(void) +{ + int pid, status; + + switch (pid = fork()) { + case -1: + assert(0); + case 0: + if (simple) { + igt_simple_init(); + + igt_skip_on_simulation(); + + exit(0); + } else { + if (list_subtests) + igt_subtest_init(2, argv_list); + else + igt_subtest_init(1, argv_run); + + if (in_fixture) { + igt_fixture + igt_skip_on_simulation(); + } if (in_subtest) { + igt_subtest("sim") + igt_skip_on_simulation(); + } else + igt_skip_on_simulation(); + + if (!in_subtest) + igt_subtest("foo") + ; + + igt_exit(); + } + default: + while (waitpid(pid, &status, 0) == -1 && + errno == EINTR) + ; + + assert(WIFEXITED(status)); + + return WEXITSTATUS(status); + } +} + +int main(int argc, char **argv) +{ + /* simple tests */ + simple = true; + assert(setenv("INTEL_SIMULATION", "1", 1) == 0); + assert(do_fork() == IGT_EXIT_SKIP); + + assert(setenv("INTEL_SIMULATION", "0", 1) == 0); + assert(do_fork() == IGT_EXIT_SUCCESS); + + /* subtests, list mode */ + simple = false; + list_subtests = true; + + in_fixture = false; + assert(setenv("INTEL_SIMULATION", "1", 1) == 0); + assert(do_fork() == IGT_EXIT_SUCCESS); + + assert(setenv("INTEL_SIMULATION", "0", 1) == 0); + assert(do_fork() == IGT_EXIT_SUCCESS); + + in_fixture = true; + assert(setenv("INTEL_SIMULATION", "1", 1) == 0); + assert(do_fork() == IGT_EXIT_SUCCESS); + + assert(setenv("INTEL_SIMULATION", "0", 1) == 0); + assert(do_fork() == IGT_EXIT_SUCCESS); + + in_fixture = false; + in_subtest = true; + assert(setenv("INTEL_SIMULATION", "1", 1) == 0); + assert(do_fork() == IGT_EXIT_SUCCESS); + + assert(setenv("INTEL_SIMULATION", "0", 1) == 0); + assert(do_fork() == IGT_EXIT_SUCCESS); + + /* subtest, run mode */ + simple = false; + list_subtests = false; + + in_fixture = false; + assert(setenv("INTEL_SIMULATION", "1", 1) == 0); + assert(do_fork() == IGT_EXIT_SKIP); + + assert(setenv("INTEL_SIMULATION", "0", 1) == 0); + assert(do_fork() == IGT_EXIT_SUCCESS); + + in_fixture = true; + assert(setenv("INTEL_SIMULATION", "1", 1) == 0); + assert(do_fork() == IGT_EXIT_SKIP); + + assert(setenv("INTEL_SIMULATION", "0", 1) == 0); + assert(do_fork() == IGT_EXIT_SUCCESS); + + in_fixture = false; + in_subtest = true; + assert(setenv("INTEL_SIMULATION", "1", 1) == 0); + assert(do_fork() == IGT_EXIT_SKIP); + + assert(setenv("INTEL_SIMULATION", "0", 1) == 0); + assert(do_fork() == IGT_EXIT_SUCCESS); + + return 0; +} diff --git a/tests/kms_addfb.c b/tests/kms_addfb.c new file mode 100644 index 00000000..349e7fb9 --- /dev/null +++ b/tests/kms_addfb.c @@ -0,0 +1,229 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Daniel Vetter <daniel.vetter@ffwll.ch> + * + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include "drm.h" +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "drm_fourcc.h" + +uint32_t gem_bo; +uint32_t gem_bo_small; + +static void pitch_tests(int fd) +{ + struct drm_mode_fb_cmd2 f = {}; + int bad_pitches[] = { 0, 32, 63, 128, 256, 256*4, 999, 64*1024 }; + int i; + + f.width = 512; + f.height = 512; + f.pixel_format = DRM_FORMAT_XRGB8888; + f.pitches[0] = 1024*4; + + igt_fixture { + gem_bo = gem_create(fd, 1024*1024*4); + igt_assert(gem_bo); + } + + igt_subtest("no-handle") { + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == -1 && + errno == EINVAL); + } + + f.handles[0] = gem_bo; + igt_subtest("normal") { + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == 0); + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0); + f.fb_id = 0; + } + + for (i = 0; i < ARRAY_SIZE(bad_pitches); i++) { + igt_subtest_f("bad-pitch-%i", bad_pitches[i]) { + f.pitches[0] = bad_pitches[i]; + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == -1 && + errno == EINVAL); + } + } + + igt_fixture + gem_set_tiling(fd, gem_bo, I915_TILING_X, 1024*4); + f.pitches[0] = 1024*4; + + igt_subtest("X-tiled") { + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == 0); + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0); + f.fb_id = 0; + } + + igt_subtest("framebuffer-vs-set-tiling") { + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == 0); + igt_assert(__gem_set_tiling(fd, gem_bo, I915_TILING_X, 512*4) == -EBUSY); + igt_assert(__gem_set_tiling(fd, gem_bo, I915_TILING_X, 1024*4) == -EBUSY); + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0); + f.fb_id = 0; + } + + f.pitches[0] = 512*4; + igt_subtest("tile-pitch-mismatch") { + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == -1 && + errno == EINVAL); + } + + igt_fixture + gem_set_tiling(fd, gem_bo, I915_TILING_Y, 1024*4); + f.pitches[0] = 1024*4; + igt_subtest("Y-tiled") { + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == -1 && + errno == EINVAL); + } + + igt_fixture + gem_close(fd, gem_bo); +} + +static void size_tests(int fd) +{ + struct drm_mode_fb_cmd2 f = {}; + struct drm_mode_fb_cmd2 f_16 = {}; + struct drm_mode_fb_cmd2 f_8 = {}; + + f.width = 1024; + f.height = 1024; + f.pixel_format = DRM_FORMAT_XRGB8888; + f.pitches[0] = 1024*4; + + f_16.width = 1024; + f_16.height = 1024*2; + f_16.pixel_format = DRM_FORMAT_RGB565; + f_16.pitches[0] = 1024*2; + + f_8.width = 1024*2; + f_8.height = 1024*2; + f_8.pixel_format = DRM_FORMAT_C8; + f_8.pitches[0] = 1024*2; + + igt_fixture { + gem_bo = gem_create(fd, 1024*1024*4); + igt_assert(gem_bo); + gem_bo_small = gem_create(fd, 1024*1024*4 - 4096); + igt_assert(gem_bo_small); + } + + f.handles[0] = gem_bo; + f_16.handles[0] = gem_bo; + f_8.handles[0] = gem_bo; + + igt_subtest("size-max") { + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == 0); + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0); + f.fb_id = 0; + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f_16) == 0); + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f_16.fb_id) == 0); + f.fb_id = 0; + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f_8) == 0); + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f_8.fb_id) == 0); + f.fb_id = 0; + } + + f.width++; + f_16.width++; + f_8.width++; + igt_subtest("too-wide") { + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == -1 && + errno == EINVAL); + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f_16) == -1 && + errno == EINVAL); + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f_8) == -1 && + errno == EINVAL); + } + f.width--; + f_16.width--; + f_8.width--; + f.height++; + f_16.height++; + f_8.height++; + igt_subtest("too-high") { + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == -1 && + errno == EINVAL); + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f_16) == -1 && + errno == EINVAL); + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f_8) == -1 && + errno == EINVAL); + } + + f.handles[0] = gem_bo_small; + igt_subtest("bo-too-small") { + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == -1 && + errno == EINVAL); + } + + /* Just to check that the parameters would work. */ + f.height = 1020; + igt_subtest("small-bo") { + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == 0); + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0); + f.fb_id = 0; + } + + igt_fixture + gem_set_tiling(fd, gem_bo_small, I915_TILING_X, 1024*4); + + igt_subtest("bo-too-small-due-to-tiling") { + igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == -1 && + errno == EINVAL); + } + + + igt_fixture { + gem_close(fd, gem_bo); + gem_close(fd, gem_bo_small); + } +} + +int fd; + +igt_main +{ + igt_fixture + fd = drm_open_any(); + + pitch_tests(fd); + + size_tests(fd); + + igt_fixture + close(fd); +} diff --git a/tests/kms_cursor_crc.c b/tests/kms_cursor_crc.c new file mode 100644 index 00000000..1b8da268 --- /dev/null +++ b/tests/kms_cursor_crc.c @@ -0,0 +1,470 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include <errno.h> +#include <limits.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> + +#include "drmtest.h" +#include "igt_debugfs.h" +#include "igt_kms.h" + +#ifndef DRM_CAP_CURSOR_WIDTH +#define DRM_CAP_CURSOR_WIDTH 0x8 +#endif +#ifndef DRM_CAP_CURSOR_HEIGHT +#define DRM_CAP_CURSOR_HEIGHT 0x9 +#endif + +typedef struct { + int drm_fd; + igt_display_t display; + struct igt_fb primary_fb; + struct igt_fb fb; +} data_t; + +typedef struct { + data_t *data; + igt_output_t *output; + enum pipe pipe; + igt_crc_t ref_crc; + int left, right, top, bottom; + int screenw, screenh; + int curw, curh; /* cursor size */ + int cursor_max_size; + igt_pipe_crc_t *pipe_crc; +} test_data_t; + +static void draw_cursor(cairo_t *cr, int x, int y, int w) +{ + w /= 2; + /* Cairo doesn't like to be fed numbers that are too wild */ + if ((x < SHRT_MIN) || (x > SHRT_MAX) || (y < SHRT_MIN) || (y > SHRT_MAX)) + return; + cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); + /* 4 color rectangles in the corners, RGBY */ + igt_paint_color_alpha(cr, x, y, w, w, 1.0, 0.0, 0.0, 1.0); + igt_paint_color_alpha(cr, x + w, y, w, w, 0.0, 1.0, 0.0, 1.0); + igt_paint_color_alpha(cr, x, y + w, w, w, 0.0, 0.0, 1.0, 1.0); + igt_paint_color_alpha(cr, x + w, y + w, w, w, 0.5, 0.5, 0.5, 1.0); +} + +static void cursor_enable(test_data_t *test_data) +{ + data_t *data = test_data->data; + igt_display_t *display = &data->display; + igt_output_t *output = test_data->output; + igt_plane_t *cursor; + + cursor = igt_output_get_plane(output, IGT_PLANE_CURSOR); + igt_plane_set_fb(cursor, &data->fb); + igt_display_commit(display); +} + +static void cursor_disable(test_data_t *test_data) +{ + data_t *data = test_data->data; + igt_display_t *display = &data->display; + igt_output_t *output = test_data->output; + igt_plane_t *cursor; + + cursor = igt_output_get_plane(output, IGT_PLANE_CURSOR); + igt_plane_set_fb(cursor, NULL); + igt_display_commit(display); +} + + +static void do_single_test(test_data_t *test_data, int x, int y) +{ + data_t *data = test_data->data; + igt_display_t *display = &data->display; + igt_pipe_crc_t *pipe_crc = test_data->pipe_crc; + igt_crc_t crc, ref_crc; + igt_plane_t *cursor; + cairo_t *cr = igt_get_cairo_ctx(data->drm_fd, &data->primary_fb); + + igt_info("."); fflush(stdout); + + /* Hardware test */ + igt_paint_test_pattern(cr, test_data->screenw, test_data->screenh); + cursor_enable(test_data); + cursor = igt_output_get_plane(test_data->output, IGT_PLANE_CURSOR); + igt_plane_set_position(cursor, x, y); + igt_display_commit(display); + igt_wait_for_vblank(data->drm_fd, test_data->pipe); + igt_pipe_crc_collect_crc(pipe_crc, &crc); + cursor_disable(test_data); + + /* Now render the same in software and collect crc */ + draw_cursor(cr, x, y, test_data->curw); + igt_display_commit(display); + igt_wait_for_vblank(data->drm_fd, test_data->pipe); + igt_pipe_crc_collect_crc(pipe_crc, &ref_crc); + /* Clear screen afterwards */ + igt_paint_color(cr, 0, 0, test_data->screenw, test_data->screenh, + 0.0, 0.0, 0.0); + + igt_assert(igt_crc_equal(&crc, &ref_crc)); +} + +static void do_test(test_data_t *test_data, + int left, int right, int top, int bottom) +{ + do_single_test(test_data, left, top); + do_single_test(test_data, right, top); + do_single_test(test_data, right, bottom); + do_single_test(test_data, left, bottom); +} + +static void test_crc_onscreen(test_data_t *test_data) +{ + int left = test_data->left; + int right = test_data->right; + int top = test_data->top; + int bottom = test_data->bottom; + int cursor_w = test_data->curw; + int cursor_h = test_data->curh; + + /* fully inside */ + do_test(test_data, left, right, top, bottom); + + /* 2 pixels inside */ + do_test(test_data, left - (cursor_w-2), right + (cursor_w-2), top , bottom ); + do_test(test_data, left , right , top - (cursor_h-2), bottom + (cursor_h-2)); + do_test(test_data, left - (cursor_w-2), right + (cursor_w-2), top - (cursor_h-2), bottom + (cursor_h-2)); + + /* 1 pixel inside */ + do_test(test_data, left - (cursor_w-1), right + (cursor_w-1), top , bottom ); + do_test(test_data, left , right , top - (cursor_h-1), bottom + (cursor_h-1)); + do_test(test_data, left - (cursor_w-1), right + (cursor_w-1), top - (cursor_h-1), bottom + (cursor_h-1)); +} + +static void test_crc_offscreen(test_data_t *test_data) +{ + int left = test_data->left; + int right = test_data->right; + int top = test_data->top; + int bottom = test_data->bottom; + int cursor_w = test_data->curw; + int cursor_h = test_data->curh; + + /* fully outside */ + do_test(test_data, left - (cursor_w), right + (cursor_w), top , bottom ); + do_test(test_data, left , right , top - (cursor_h), bottom + (cursor_h)); + do_test(test_data, left - (cursor_w), right + (cursor_w), top - (cursor_h), bottom + (cursor_h)); + + /* fully outside by 1 extra pixels */ + do_test(test_data, left - (cursor_w+1), right + (cursor_w+1), top , bottom ); + do_test(test_data, left , right , top - (cursor_h+1), bottom + (cursor_h+1)); + do_test(test_data, left - (cursor_w+1), right + (cursor_w+1), top - (cursor_h+1), bottom + (cursor_h+1)); + + /* fully outside by 2 extra pixels */ + do_test(test_data, left - (cursor_w+2), right + (cursor_w+2), top , bottom ); + do_test(test_data, left , right , top - (cursor_h+2), bottom + (cursor_h+2)); + do_test(test_data, left - (cursor_w+2), right + (cursor_w+2), top - (cursor_h+2), bottom + (cursor_h+2)); + + /* fully outside by a lot of extra pixels */ + do_test(test_data, left - (cursor_w+512), right + (cursor_w+512), top , bottom ); + do_test(test_data, left , right , top - (cursor_h+512), bottom + (cursor_h+512)); + do_test(test_data, left - (cursor_w+512), right + (cursor_w+512), top - (cursor_h+512), bottom + (cursor_h+512)); + + /* go nuts */ + do_test(test_data, INT_MIN, INT_MAX, INT_MIN, INT_MAX); +} + +static void test_crc_sliding(test_data_t *test_data) +{ + int i; + + /* Make sure cursor moves smoothly and pixel-by-pixel, and that there are + * no alignment issues. Horizontal, vertical and diagonal test. + */ + for (i = 0; i < 16; i++) { + do_single_test(test_data, i, 0); + do_single_test(test_data, 0, i); + do_single_test(test_data, i, i); + } +} + +static void test_crc_random(test_data_t *test_data) +{ + int i; + + /* Random cursor placement */ + for (i = 0; i < 50; i++) { + int x = rand() % (test_data->screenw + test_data->curw * 2) - test_data->curw; + int y = rand() % (test_data->screenh + test_data->curh * 2) - test_data->curh; + do_single_test(test_data, x, y); + } +} + +static bool prepare_crtc(test_data_t *test_data, igt_output_t *output, + int cursor_w, int cursor_h) +{ + drmModeModeInfo *mode; + data_t *data = test_data->data; + igt_display_t *display = &data->display; + igt_plane_t *primary; + + /* select the pipe we want to use */ + igt_output_set_pipe(output, test_data->pipe); + igt_display_commit(display); + + if (!output->valid) { + igt_output_set_pipe(output, PIPE_ANY); + igt_display_commit(display); + return false; + } + + /* create and set the primary plane fb */ + mode = igt_output_get_mode(output); + igt_create_color_fb(data->drm_fd, mode->hdisplay, mode->vdisplay, + DRM_FORMAT_XRGB8888, + false, /* tiled */ + 0.0, 0.0, 0.0, + &data->primary_fb); + + primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY); + igt_plane_set_fb(primary, &data->primary_fb); + + igt_display_commit(display); + + /* create the pipe_crc object for this pipe */ + if (test_data->pipe_crc) + igt_pipe_crc_free(test_data->pipe_crc); + + test_data->pipe_crc = igt_pipe_crc_new(test_data->pipe, + INTEL_PIPE_CRC_SOURCE_AUTO); + if (!test_data->pipe_crc) { + igt_info("auto crc not supported on this connector with pipe %i\n", + test_data->pipe); + return false; + } + + /* x/y position where the cursor is still fully visible */ + test_data->left = 0; + test_data->right = mode->hdisplay - cursor_w; + test_data->top = 0; + test_data->bottom = mode->vdisplay - cursor_h; + test_data->screenw = mode->hdisplay; + test_data->screenh = mode->vdisplay; + test_data->curw = cursor_w; + test_data->curh = cursor_h; + test_data->cursor_max_size = cursor_w; + + /* make sure cursor is disabled */ + cursor_disable(test_data); + igt_wait_for_vblank(data->drm_fd, test_data->pipe); + + /* get reference crc w/o cursor */ + igt_pipe_crc_collect_crc(test_data->pipe_crc, &test_data->ref_crc); + + return true; +} + +static void cleanup_crtc(test_data_t *test_data, igt_output_t *output) +{ + data_t *data = test_data->data; + igt_display_t *display = &data->display; + igt_plane_t *primary; + + igt_pipe_crc_free(test_data->pipe_crc); + test_data->pipe_crc = NULL; + + igt_remove_fb(data->drm_fd, &data->primary_fb); + + primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY); + igt_plane_set_fb(primary, NULL); + + igt_output_set_pipe(output, PIPE_ANY); + igt_display_commit(display); +} + +static void run_test(data_t *data, void (*testfunc)(test_data_t *), int cursor_w, int cursor_h) +{ + igt_display_t *display = &data->display; + igt_output_t *output; + enum pipe p; + test_data_t test_data = { + .data = data, + }; + int valid_tests = 0; + + for_each_connected_output(display, output) { + test_data.output = output; + for (p = 0; p < igt_display_get_n_pipes(display); p++) { + test_data.pipe = p; + + if (!prepare_crtc(&test_data, output, cursor_w, cursor_h)) + continue; + + valid_tests++; + + igt_info("Beginning %s on pipe %c, connector %s\n", + igt_subtest_name(), pipe_name(test_data.pipe), + igt_output_name(output)); + + testfunc(&test_data); + + igt_info("\n%s on pipe %c, connector %s: PASSED\n\n", + igt_subtest_name(), pipe_name(test_data.pipe), + igt_output_name(output)); + + /* cleanup what prepare_crtc() has done */ + cleanup_crtc(&test_data, output); + } + } + + igt_require_f(valid_tests, "no valid crtc/connector combinations found\n"); +} + +static void create_cursor_fb(data_t *data, int cur_w, int cur_h) +{ + cairo_t *cr; + uint32_t fb_id; + + fb_id = igt_create_fb(data->drm_fd, cur_w, cur_h, + DRM_FORMAT_ARGB8888, false, + &data->fb); + igt_assert(fb_id); + + cr = igt_get_cairo_ctx(data->drm_fd, &data->fb); + draw_cursor(cr, 0, 0, cur_w); + igt_assert(cairo_status(cr) == 0); +} + +static void test_cursor_size(test_data_t *test_data) +{ + data_t *data = test_data->data; + igt_display_t *display = &data->display; + igt_pipe_crc_t *pipe_crc = test_data->pipe_crc; + igt_crc_t crc[10], ref_crc; + igt_plane_t *cursor; + cairo_t *cr; + uint32_t fb_id; + int i, size, cursor_max_size = test_data->cursor_max_size; + + /* Create a maximum size cursor, then change the size in flight to + * smaller ones to see that the size is applied correctly + */ + fb_id = igt_create_fb(data->drm_fd, cursor_max_size, cursor_max_size, + DRM_FORMAT_ARGB8888, false, &data->fb); + igt_assert(fb_id); + + /* Use a solid white rectangle as the cursor */ + cr = igt_get_cairo_ctx(data->drm_fd, &data->fb); + igt_paint_color_alpha(cr, 0, 0, cursor_max_size, cursor_max_size, 1.0, 1.0, 1.0, 1.0); + + /* Hardware test loop */ + cursor_enable(test_data); + cursor = igt_output_get_plane(test_data->output, IGT_PLANE_CURSOR); + igt_plane_set_position(cursor, 0, 0); + for (i = 0, size = cursor_max_size; size >= 64; size /= 2, i++) { + /* Change size in flight: */ + int ret = drmModeSetCursor(data->drm_fd, test_data->output->config.crtc->crtc_id, + data->fb.gem_handle, size, size); + igt_assert(ret == 0); + igt_wait_for_vblank(data->drm_fd, test_data->pipe); + igt_pipe_crc_collect_crc(pipe_crc, &crc[i]); + } + cursor_disable(test_data); + /* Software test loop */ + cr = igt_get_cairo_ctx(data->drm_fd, &data->primary_fb); + for (i = 0, size = cursor_max_size; size >= 64; size /= 2, i++) { + /* Now render the same in software and collect crc */ + igt_paint_color_alpha(cr, 0, 0, size, size, 1.0, 1.0, 1.0, 1.0); + igt_display_commit(display); + igt_wait_for_vblank(data->drm_fd, test_data->pipe); + igt_pipe_crc_collect_crc(pipe_crc, &ref_crc); + /* Clear screen afterwards */ + igt_paint_color(cr, 0, 0, test_data->screenw, test_data->screenh, + 0.0, 0.0, 0.0); + igt_assert(igt_crc_equal(&crc[i], &ref_crc)); + } +} + +static void run_test_generic(data_t *data, int cursor_max_size) +{ + int cursor_size; + for (cursor_size = 64; cursor_size <= 256; cursor_size *= 2) + { + igt_fixture + igt_require(cursor_max_size >= cursor_size); + + igt_fixture + create_cursor_fb(data, cursor_size, cursor_size); + + /* Using created cursor FBs to test cursor support */ + igt_subtest_f("cursor-%d-onscreen", cursor_size) + run_test(data, test_crc_onscreen, cursor_size, cursor_size); + igt_subtest_f("cursor-%d-offscreen", cursor_size) + run_test(data, test_crc_offscreen, cursor_size, cursor_size); + igt_subtest_f("cursor-%d-sliding", cursor_size) + run_test(data, test_crc_sliding, cursor_size, cursor_size); + igt_subtest_f("cursor-%d-random", cursor_size) + run_test(data, test_crc_random, cursor_size, cursor_size); + + igt_fixture + igt_remove_fb(data->drm_fd, &data->fb); + } +} + +igt_main +{ + uint64_t cursor_width = 64, cursor_height = 64; + data_t data = {}; + int ret; + + igt_skip_on_simulation(); + + igt_fixture { + data.drm_fd = drm_open_any(); + + ret = drmGetCap(data.drm_fd, DRM_CAP_CURSOR_WIDTH, &cursor_width); + igt_assert(ret == 0 || errno == EINVAL); + /* Not making use of cursor_height since it is same as width, still reading */ + ret = drmGetCap(data.drm_fd, DRM_CAP_CURSOR_HEIGHT, &cursor_height); + igt_assert(ret == 0 || errno == EINVAL); + + /* We assume width and height are same so max is assigned width */ + igt_assert_cmpint(cursor_width, ==, cursor_height); + + igt_set_vt_graphics_mode(); + + igt_require_pipe_crc(); + + igt_display_init(&data.display, data.drm_fd); + } + + igt_subtest_f("cursor-size-change") + run_test(&data, test_cursor_size, cursor_width, cursor_height); + + run_test_generic(&data, cursor_width); + + igt_fixture { + igt_display_fini(&data.display); + } +} diff --git a/tests/kms_fbc_crc.c b/tests/kms_fbc_crc.c new file mode 100644 index 00000000..810f6f34 --- /dev/null +++ b/tests/kms_fbc_crc.c @@ -0,0 +1,531 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> + +#include "drmtest.h" +#include "igt_debugfs.h" +#include "igt_kms.h" +#include "intel_chipset.h" +#include "intel_batchbuffer.h" +#include "ioctl_wrappers.h" + +enum test_mode { + TEST_PAGE_FLIP, + TEST_MMAP_CPU, + TEST_MMAP_GTT, + TEST_BLT, + TEST_RENDER, + TEST_CONTEXT, + TEST_PAGE_FLIP_AND_MMAP_CPU, + TEST_PAGE_FLIP_AND_MMAP_GTT, + TEST_PAGE_FLIP_AND_BLT, + TEST_PAGE_FLIP_AND_RENDER, + TEST_PAGE_FLIP_AND_CONTEXT, +}; + +typedef struct { + int drm_fd; + igt_crc_t ref_crc[2]; + igt_pipe_crc_t *pipe_crc; + drm_intel_bufmgr *bufmgr; + drm_intel_context *ctx[2]; + uint32_t devid; + uint32_t handle[2]; + igt_display_t display; + igt_output_t *output; + enum pipe pipe; + igt_plane_t *primary; + struct igt_fb fb[2]; + uint32_t fb_id[2]; +} data_t; + +static const char *test_mode_str(enum test_mode mode) +{ + static const char * const test_modes[] = { + [TEST_PAGE_FLIP] = "page_flip", + [TEST_MMAP_CPU] = "mmap_cpu", + [TEST_MMAP_GTT] = "mmap_gtt", + [TEST_BLT] = "blt", + [TEST_RENDER] = "render", + [TEST_CONTEXT] = "context", + [TEST_PAGE_FLIP_AND_MMAP_CPU] = "page_flip_and_mmap_cpu", + [TEST_PAGE_FLIP_AND_MMAP_GTT] = "page_flip_and_mmap_gtt", + [TEST_PAGE_FLIP_AND_BLT] = "page_flip_and_blt", + [TEST_PAGE_FLIP_AND_RENDER] = "page_flip_and_render", + [TEST_PAGE_FLIP_AND_CONTEXT] = "page_flip_and_context", + }; + + return test_modes[mode]; +} + +static void fill_blt(data_t *data, uint32_t handle, unsigned char color) +{ + drm_intel_bo *dst = gem_handle_to_libdrm_bo(data->bufmgr, + data->drm_fd, + "", handle); + struct intel_batchbuffer *batch; + + batch = intel_batchbuffer_alloc(data->bufmgr, data->devid); + igt_assert(batch); + + BEGIN_BATCH(5); + OUT_BATCH(COLOR_BLT_CMD); + OUT_BATCH((1 << 24) | (0xf0 << 16) | 0); + OUT_BATCH(1 << 16 | 4); + OUT_RELOC(dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + OUT_BATCH(color); + ADVANCE_BATCH(); + + intel_batchbuffer_flush(batch); + intel_batchbuffer_free(batch); + + gem_bo_busy(data->drm_fd, handle); +} + +static void scratch_buf_init(struct igt_buf *buf, drm_intel_bo *bo) +{ + buf->bo = bo; + buf->stride = 4096; + buf->tiling = I915_TILING_X; + buf->size = 4096; +} + +static void exec_nop(data_t *data, uint32_t handle, drm_intel_context *context) +{ + drm_intel_bo *dst; + struct intel_batchbuffer *batch; + + dst = gem_handle_to_libdrm_bo(data->bufmgr, data->drm_fd, "", handle); + igt_assert(dst); + + batch = intel_batchbuffer_alloc(data->bufmgr, data->devid); + igt_assert(batch); + + /* add the reloc to make sure the kernel will think we write to dst */ + BEGIN_BATCH(4); + OUT_BATCH(MI_BATCH_BUFFER_END); + OUT_BATCH(MI_NOOP); + OUT_RELOC(dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + OUT_BATCH(MI_NOOP); + ADVANCE_BATCH(); + + intel_batchbuffer_flush_with_context(batch, context); + intel_batchbuffer_free(batch); +} + +static void fill_render(data_t *data, uint32_t handle, + drm_intel_context *context, unsigned char color) +{ + drm_intel_bo *src, *dst; + struct intel_batchbuffer *batch; + struct igt_buf src_buf, dst_buf; + const uint8_t buf[4] = { color, color, color, color }; + igt_render_copyfunc_t rendercopy = igt_get_render_copyfunc(data->devid); + + igt_skip_on(!rendercopy); + + dst = gem_handle_to_libdrm_bo(data->bufmgr, data->drm_fd, "", handle); + igt_assert(dst); + + src = drm_intel_bo_alloc(data->bufmgr, "", 4096, 4096); + igt_assert(src); + + gem_write(data->drm_fd, src->handle, 0, buf, 4); + + scratch_buf_init(&src_buf, src); + scratch_buf_init(&dst_buf, dst); + + batch = intel_batchbuffer_alloc(data->bufmgr, data->devid); + igt_assert(batch); + + rendercopy(batch, context, + &src_buf, 0, 0, 1, 1, + &dst_buf, 0, 0); + + intel_batchbuffer_free(batch); + + gem_bo_busy(data->drm_fd, handle); +} + +static bool fbc_enabled(data_t *data) +{ + FILE *status; + char str[64] = {}; + + status = igt_debugfs_fopen("i915_fbc_status", "r"); + igt_assert(status); + + fread(str, sizeof(str) - 1, 1, status); + fclose(status); + return strstr(str, "FBC enabled") != NULL; +} + +static void test_crc(data_t *data, enum test_mode mode) +{ + uint32_t crtc_id = data->output->config.crtc->crtc_id; + igt_pipe_crc_t *pipe_crc = data->pipe_crc; + igt_crc_t *crcs = NULL; + uint32_t handle = data->handle[0]; + + igt_assert(fbc_enabled(data)); + + if (mode >= TEST_PAGE_FLIP_AND_MMAP_CPU) { + handle = data->handle[1]; + igt_assert(drmModePageFlip(data->drm_fd, crtc_id, + data->fb_id[1], 0, NULL) == 0); + usleep(300000); + + igt_assert(fbc_enabled(data)); + } + + switch (mode) { + void *ptr; + case TEST_PAGE_FLIP: + igt_assert(drmModePageFlip(data->drm_fd, crtc_id, + data->fb_id[1], 0, NULL) == 0); + break; + case TEST_MMAP_CPU: + case TEST_PAGE_FLIP_AND_MMAP_CPU: + ptr = gem_mmap__cpu(data->drm_fd, handle, 4096, PROT_WRITE); + gem_set_domain(data->drm_fd, handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); + memset(ptr, 0xff, 4); + munmap(ptr, 4096); + gem_sw_finish(data->drm_fd, handle); + break; + case TEST_MMAP_GTT: + case TEST_PAGE_FLIP_AND_MMAP_GTT: + ptr = gem_mmap__gtt(data->drm_fd, handle, 4096, PROT_WRITE); + gem_set_domain(data->drm_fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); + memset(ptr, 0xff, 4); + munmap(ptr, 4096); + break; + case TEST_BLT: + case TEST_PAGE_FLIP_AND_BLT: + fill_blt(data, handle, 0xff); + break; + case TEST_RENDER: + case TEST_CONTEXT: + case TEST_PAGE_FLIP_AND_RENDER: + case TEST_PAGE_FLIP_AND_CONTEXT: + fill_render(data, handle, + (mode == TEST_CONTEXT || mode == TEST_PAGE_FLIP_AND_CONTEXT) ? + data->ctx[1] : NULL, 0xff); + break; + } + + /* + * Make sure we're looking at new data (two vblanks + * to leave some leeway for the kernel if we ever do + * some kind of delayed FBC disable for GTT mmaps. + */ + igt_wait_for_vblank(data->drm_fd, data->pipe); + igt_wait_for_vblank(data->drm_fd, data->pipe); + + igt_pipe_crc_start(pipe_crc); + igt_pipe_crc_get_crcs(pipe_crc, 1, &crcs); + igt_pipe_crc_stop(pipe_crc); + igt_assert(!igt_crc_equal(&crcs[0], &data->ref_crc[0])); + if (mode == TEST_PAGE_FLIP) + igt_assert(igt_crc_equal(&crcs[0], &data->ref_crc[1])); + else + igt_assert(!igt_crc_equal(&crcs[0], &data->ref_crc[1])); + free(crcs); + + /* + * Allow time for FBC to kick in again if it + * got disabled during dirtyfb or page flip. + */ + usleep(300000); + + igt_assert(fbc_enabled(data)); + + igt_pipe_crc_start(pipe_crc); + igt_pipe_crc_get_crcs(pipe_crc, 1, &crcs); + igt_pipe_crc_stop(pipe_crc); + igt_assert(!igt_crc_equal(&crcs[0], &data->ref_crc[0])); + if (mode == TEST_PAGE_FLIP) + igt_assert(igt_crc_equal(&crcs[0], &data->ref_crc[1])); + else + igt_assert(!igt_crc_equal(&crcs[0], &data->ref_crc[1])); + free(crcs); +} + +static bool prepare_crtc(data_t *data) +{ + igt_display_t *display = &data->display; + igt_output_t *output = data->output; + + /* select the pipe we want to use */ + igt_output_set_pipe(output, data->pipe); + igt_display_commit(display); + + if (!output->valid) { + igt_output_set_pipe(output, PIPE_ANY); + igt_display_commit(display); + return false; + } + + return true; +} + +static bool prepare_test(data_t *data, enum test_mode test_mode) +{ + igt_display_t *display = &data->display; + igt_output_t *output = data->output; + drmModeModeInfo *mode; + igt_pipe_crc_t *pipe_crc; + igt_crc_t *crcs = NULL; + + data->primary = igt_output_get_plane(data->output, IGT_PLANE_PRIMARY); + mode = igt_output_get_mode(data->output); + + data->fb_id[0] = igt_create_color_fb(data->drm_fd, mode->hdisplay, mode->vdisplay, + DRM_FORMAT_XRGB8888, + true, /* tiled */ + 0.0, 0.0, 0.0, &data->fb[0]); + igt_assert(data->fb_id[0]); + data->fb_id[1] = igt_create_color_fb(data->drm_fd, mode->hdisplay, mode->vdisplay, + DRM_FORMAT_XRGB8888, + true, /* tiled */ + 0.1, 0.1, 0.1, + &data->fb[1]); + igt_assert(data->fb_id[1]); + + data->handle[0] = data->fb[0].gem_handle; + data->handle[1] = data->fb[1].gem_handle; + + /* scanout = fb[1] */ + igt_plane_set_fb(data->primary, &data->fb[1]); + igt_display_commit(display); + usleep(300000); + + if (!fbc_enabled(data)) { + igt_info("FBC not enabled\n"); + + igt_plane_set_fb(data->primary, NULL); + igt_output_set_pipe(output, PIPE_ANY); + igt_display_commit(display); + + igt_remove_fb(data->drm_fd, &data->fb[0]); + igt_remove_fb(data->drm_fd, &data->fb[1]); + return false; + } + + igt_pipe_crc_free(data->pipe_crc); + data->pipe_crc = NULL; + + pipe_crc = igt_pipe_crc_new(data->pipe, + INTEL_PIPE_CRC_SOURCE_AUTO); + if (!pipe_crc) { + igt_info("auto crc not supported on this connector with crtc %i\n", + data->pipe); + + igt_plane_set_fb(data->primary, NULL); + igt_output_set_pipe(output, PIPE_ANY); + igt_display_commit(display); + + igt_remove_fb(data->drm_fd, &data->fb[0]); + igt_remove_fb(data->drm_fd, &data->fb[1]); + return false; + } + + data->pipe_crc = pipe_crc; + + igt_wait_for_vblank(data->drm_fd, data->pipe); + + /* get reference crc for fb[1] */ + igt_pipe_crc_start(pipe_crc); + igt_pipe_crc_get_crcs(pipe_crc, 1, &crcs); + data->ref_crc[1] = crcs[0]; + igt_pipe_crc_stop(pipe_crc); + free(crcs); + + if (test_mode == TEST_CONTEXT || test_mode == TEST_PAGE_FLIP_AND_CONTEXT) { + data->ctx[0] = drm_intel_gem_context_create(data->bufmgr); + igt_assert(data->ctx[0]); + data->ctx[1] = drm_intel_gem_context_create(data->bufmgr); + igt_assert(data->ctx[1]); + + /* + * Disable FBC RT address for both contexts + * (by "rendering" to a non-scanout buffer). + */ + exec_nop(data, data->handle[0], data->ctx[1]); + exec_nop(data, data->handle[0], data->ctx[0]); + exec_nop(data, data->handle[0], data->ctx[1]); + exec_nop(data, data->handle[0], data->ctx[0]); + } + + /* scanout = fb[0] */ + igt_plane_set_fb(data->primary, &data->fb[0]); + igt_display_commit(display); + usleep(300000); + + igt_assert(fbc_enabled(data)); + + if (test_mode == TEST_CONTEXT || test_mode == TEST_PAGE_FLIP_AND_CONTEXT) { + /* + * make ctx[0] FBC RT address point to fb[0], ctx[1] + * FBC RT address is left as disabled. + */ + exec_nop(data, data->fb[0].gem_handle, data->ctx[0]); + } + + igt_wait_for_vblank(data->drm_fd, data->pipe); + + /* get reference crc for fb[0] */ + igt_pipe_crc_start(pipe_crc); + igt_pipe_crc_get_crcs(pipe_crc, 1, &crcs); + data->ref_crc[0] = crcs[0]; + igt_pipe_crc_stop(pipe_crc); + free(crcs); + + return true; +} + +static void finish_crtc(data_t *data, enum test_mode mode) +{ + igt_pipe_crc_free(data->pipe_crc); + data->pipe_crc = NULL; + + if (mode == TEST_CONTEXT || mode == TEST_PAGE_FLIP_AND_CONTEXT) { + drm_intel_gem_context_destroy(data->ctx[0]); + drm_intel_gem_context_destroy(data->ctx[1]); + } + + igt_plane_set_fb(data->primary, NULL); + igt_output_set_pipe(data->output, PIPE_ANY); + igt_display_commit(&data->display); + + igt_remove_fb(data->drm_fd, &data->fb[0]); + igt_remove_fb(data->drm_fd, &data->fb[1]); +} + +static void reset_display(data_t *data) +{ + igt_display_t *display = &data->display; + + for_each_connected_output(display, data->output) { + if (data->output->valid) { + data->primary = igt_output_get_plane(data->output, IGT_PLANE_PRIMARY); + igt_plane_set_fb(data->primary, NULL); + } + igt_output_set_pipe(data->output, PIPE_ANY); + } +} + +static void run_test(data_t *data, enum test_mode mode) +{ + igt_display_t *display = &data->display; + int valid_tests = 0; + + if (mode == TEST_CONTEXT || mode == TEST_PAGE_FLIP_AND_CONTEXT) { + drm_intel_context *ctx = drm_intel_gem_context_create(data->bufmgr); + igt_require(ctx); + drm_intel_gem_context_destroy(ctx); + } + + reset_display(data); + + for_each_connected_output(display, data->output) { + for (data->pipe = 0; data->pipe < igt_display_get_n_pipes(display); data->pipe++) { + if (!prepare_crtc(data)) + continue; + + igt_info("Beginning %s on pipe %c, connector %s\n", + igt_subtest_name(), pipe_name(data->pipe), + igt_output_name(data->output)); + + if (!prepare_test(data, mode)) { + igt_info("%s on pipe %c, connector %s: SKIPPED\n", + igt_subtest_name(), pipe_name(data->pipe), + igt_output_name(data->output)); + continue; + } + + valid_tests++; + + test_crc(data, mode); + + igt_info("%s on pipe %c, connector %s: PASSED\n", + igt_subtest_name(), pipe_name(data->pipe), + igt_output_name(data->output)); + + finish_crtc(data, mode); + } + } + + igt_require_f(valid_tests, "no valid crtc/connector combinations found\n"); +} + +igt_main +{ + data_t data = {}; + enum test_mode mode; + + igt_skip_on_simulation(); + + igt_fixture { + char buf[64]; + FILE *status; + + data.drm_fd = drm_open_any(); + igt_set_vt_graphics_mode(); + + data.devid = intel_get_drm_devid(data.drm_fd); + + igt_require_pipe_crc(); + + status = igt_debugfs_fopen("i915_fbc_status", "r"); + igt_require_f(status, "No i915_fbc_status found\n"); + fread(buf, sizeof(buf), 1, status); + fclose(status); + buf[sizeof(buf) - 1] = '\0'; + igt_require_f(!strstr(buf, "unsupported by this chipset") && + !strstr(buf, "disabled per module param") && + !strstr(buf, "disabled per chip default"), + "FBC not supported/enabled\n"); + + data.bufmgr = drm_intel_bufmgr_gem_init(data.drm_fd, 4096); + igt_assert(data.bufmgr); + drm_intel_bufmgr_gem_enable_reuse(data.bufmgr); + + igt_display_init(&data.display, data.drm_fd); + } + + for (mode = TEST_PAGE_FLIP; mode <= TEST_PAGE_FLIP_AND_CONTEXT; mode++) { + igt_subtest_f("%s", test_mode_str(mode)) { + run_test(&data, mode); + } + } + + igt_fixture { + drm_intel_bufmgr_destroy(data.bufmgr); + igt_display_fini(&data.display); + } +} diff --git a/tests/kms_fence_pin_leak.c b/tests/kms_fence_pin_leak.c new file mode 100644 index 00000000..d3ca132f --- /dev/null +++ b/tests/kms_fence_pin_leak.c @@ -0,0 +1,239 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include <errno.h> +#include <limits.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> + +#include "drmtest.h" +#include "igt_debugfs.h" +#include "igt_kms.h" +#include "ioctl_wrappers.h" +#include "intel_chipset.h" + +typedef struct { + int drm_fd; + uint32_t devid; + drm_intel_bufmgr *bufmgr; + igt_display_t display; + drm_intel_bo *bos[64]; /* >= num fence registers */ +} data_t; + +static void exec_nop(data_t *data, uint32_t handle, drm_intel_context *context) +{ + drm_intel_bo *dst; + struct intel_batchbuffer *batch; + + dst = gem_handle_to_libdrm_bo(data->bufmgr, data->drm_fd, "", handle); + igt_assert(dst); + + batch = intel_batchbuffer_alloc(data->bufmgr, data->devid); + igt_assert(batch); + + /* add the reloc to make sure the kernel will think we write to dst */ + BEGIN_BATCH(4); + OUT_BATCH(MI_BATCH_BUFFER_END); + OUT_BATCH(MI_NOOP); + OUT_RELOC(dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + OUT_BATCH(MI_NOOP); + ADVANCE_BATCH(); + + intel_batchbuffer_flush_with_context(batch, context); + intel_batchbuffer_free(batch); + + drm_intel_bo_unreference(dst); +} + +static void alloc_fence_objs(data_t *data) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(data->bos); i++) { + drm_intel_bo *bo; + + bo = drm_intel_bo_alloc(data->bufmgr, "fence bo", 4096, 4096); + igt_assert(bo); + gem_set_tiling(data->drm_fd, bo->handle, I915_TILING_X, 512); + + data->bos[i] = bo; + } +} + +static void touch_fences(data_t *data) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(data->bos); i++) { + uint32_t handle = data->bos[i]->handle; + void *ptr; + + ptr = gem_mmap__gtt(data->drm_fd, handle, 4096, PROT_WRITE); + gem_set_domain(data->drm_fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); + memset(ptr, 0, 4); + munmap(ptr, 4096); + } +} + +static void free_fence_objs(data_t *data) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(data->bos); i++) + drm_intel_bo_unreference(data->bos[i]); +} + +static bool run_single_test(data_t *data, enum pipe pipe, igt_output_t *output) +{ + igt_display_t *display = &data->display; + drmModeModeInfo *mode; + igt_plane_t *primary; + struct igt_fb fb[2]; + int i; + + igt_output_set_pipe(output, pipe); + igt_display_commit(display); + + if (!output->valid) { + igt_output_set_pipe(output, PIPE_ANY); + igt_display_commit(display); + return false; + } + + mode = igt_output_get_mode(output); + primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY); + + igt_create_color_fb(data->drm_fd, mode->hdisplay, mode->vdisplay, + DRM_FORMAT_XRGB8888, + true, /* need a fence so must be tiled */ + 0.0, 0.0, 0.0, + &fb[0]); + igt_create_color_fb(data->drm_fd, mode->hdisplay, mode->vdisplay, + DRM_FORMAT_XRGB8888, + true, /* need a fence so must be tiled */ + 0.0, 0.0, 0.0, + &fb[1]); + + igt_plane_set_fb(primary, &fb[0]); + igt_display_commit(display); + + for (i = 0; i < 64; i++) { + drm_intel_context *ctx; + + /* + * Link fb.gem_handle to the ppgtt vm of ctx so that the context + * destruction will unbind the obj from the ppgtt vm in question. + */ + ctx = drm_intel_gem_context_create(data->bufmgr); + igt_assert(ctx); + exec_nop(data, fb[i&1].gem_handle, ctx); + drm_intel_gem_context_destroy(ctx); + + /* Force a context switch to make sure ctx gets destroyed for real. */ + exec_nop(data, fb[i&1].gem_handle, NULL); + + gem_sync(data->drm_fd, fb[i&1].gem_handle); + + /* + * Make only the current fb has a fence and + * the next fb will pick a new fence. Assuming + * all fences are associated with an object, the + * kernel will always pick a fence with pin_count==0. + */ + touch_fences(data); + + /* + * Pin the new buffer and unpin the old buffer from display. If + * the kernel is buggy the ppgtt unbind will have dropped the + * fence for the old buffer, and now the display code will try + * to unpin only to find no fence there. So the pin_count will leak. + */ + igt_plane_set_fb(primary, &fb[!(i&1)]); + igt_display_commit(display); + + printf("."); + fflush(stdout); + } + + igt_plane_set_fb(primary, NULL); + igt_output_set_pipe(output, PIPE_ANY); + igt_display_commit(display); + + igt_remove_fb(data->drm_fd, &fb[1]); + igt_remove_fb(data->drm_fd, &fb[0]); + + printf("\n"); + + return true; +} + +static void run_test(data_t *data) +{ + igt_display_t *display = &data->display; + igt_output_t *output; + enum pipe p; + + for_each_connected_output(display, output) { + for (p = 0; p < igt_display_get_n_pipes(display); p++) { + if (run_single_test(data, p, output)) + return; /* one time ought to be enough */ + } + } + + igt_skip("no valid crtc/connector combinations found\n"); +} + +igt_simple_main +{ + drm_intel_context *ctx; + data_t data = {}; + + igt_skip_on_simulation(); + + data.drm_fd = drm_open_any(); + + data.devid = intel_get_drm_devid(data.drm_fd); + + igt_set_vt_graphics_mode(); + + data.bufmgr = drm_intel_bufmgr_gem_init(data.drm_fd, 4096); + igt_assert(data.bufmgr); + drm_intel_bufmgr_gem_enable_reuse(data.bufmgr); + + igt_display_init(&data.display, data.drm_fd); + + ctx = drm_intel_gem_context_create(data.bufmgr); + igt_require(ctx); + drm_intel_gem_context_destroy(ctx); + + alloc_fence_objs(&data); + + run_test(&data); + + free_fence_objs(&data); + + drm_intel_bufmgr_destroy(data.bufmgr); + igt_display_fini(&data.display); +} diff --git a/tests/kms_flip.c b/tests/kms_flip.c new file mode 100644 index 00000000..46ce2ed1 --- /dev/null +++ b/tests/kms_flip.c @@ -0,0 +1,1651 @@ +/* + * Copyright 2012 Intel Corporation + * Jesse Barnes <jesse.barnes@intel.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <cairo.h> +#include <errno.h> +#include <fcntl.h> +#include <math.h> +#include <stdint.h> +#include <unistd.h> +#include <sys/poll.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <linux/kd.h> +#include <time.h> +#include <pthread.h> + +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_chipset.h" +#include "intel_batchbuffer.h" +#include "igt_kms.h" +#include "igt_aux.h" +#include "igt_debugfs.h" + +#define TEST_DPMS (1 << 0) +#define TEST_WITH_DUMMY_BCS (1 << 1) +#define TEST_WITH_DUMMY_RCS (1 << 2) +#define TEST_PAN (1 << 3) +#define TEST_MODESET (1 << 4) +#define TEST_CHECK_TS (1 << 5) +#define TEST_EBUSY (1 << 6) +#define TEST_EINVAL (1 << 7) +#define TEST_FLIP (1 << 8) +#define TEST_VBLANK (1 << 9) +#define TEST_VBLANK_BLOCK (1 << 10) +#define TEST_VBLANK_ABSOLUTE (1 << 11) +#define TEST_VBLANK_EXPIRED_SEQ (1 << 12) +#define TEST_FB_RECREATE (1 << 13) +#define TEST_RMFB (1 << 14) +#define TEST_HANG (1 << 15) +#define TEST_NOEVENT (1 << 16) +#define TEST_FB_BAD_TILING (1 << 17) +#define TEST_SINGLE_BUFFER (1 << 18) +#define TEST_DPMS_OFF (1 << 19) +#define TEST_NO_2X_OUTPUT (1 << 20) +#define TEST_DPMS_OFF_OTHERS (1 << 21) +#define TEST_ENOENT (1 << 22) +#define TEST_FENCE_STRESS (1 << 23) +#define TEST_VBLANK_RACE (1 << 24) +#define TEST_RPM (1 << 25) +#define TEST_SUSPEND (1 << 26) +#define TEST_TS_CONT (1 << 27) +#define TEST_BO_TOOBIG (1 << 28) +#define TEST_HANG_ONCE (1 << 29) + +#define EVENT_FLIP (1 << 0) +#define EVENT_VBLANK (1 << 1) + +#ifndef DRM_CAP_TIMESTAMP_MONOTONIC +#define DRM_CAP_TIMESTAMP_MONOTONIC 6 +#endif + +#define max(a, b) ((a) > (b) ? (a) : (b)) + +drmModeRes *resources; +int drm_fd; +static drm_intel_bufmgr *bufmgr; +struct intel_batchbuffer *batch; +uint32_t devid; +int test_time = 3; +static bool monotonic_timestamp; +static pthread_t vblank_wait_thread; + +static drmModeConnector *last_connector; + +uint32_t *fb_ptr; + +struct type_name { + int type; + const char *name; +}; + +struct event_state { + const char *name; + + /* + * Event data for the last event that has already passed our check. + * Updated using the below current_* vars in update_state(). + */ + struct timeval last_ts; /* kernel reported timestamp */ + struct timeval last_received_ts; /* the moment we received it */ + unsigned int last_seq; /* kernel reported seq. num */ + + /* + * Event data for for the current event that we just received and + * going to check for validity. Set in event_handler(). + */ + struct timeval current_ts; /* kernel reported timestamp */ + struct timeval current_received_ts; /* the moment we received it */ + unsigned int current_seq; /* kernel reported seq. num */ + + int count; /* # of events of this type */ + + /* Step between the current and next 'target' sequence number. */ + int seq_step; +}; + +struct test_output { + int mode_valid; + drmModeModeInfo kmode[4]; + drmModeEncoder *kencoder[4]; + drmModeConnector *kconnector[4]; + uint32_t _connector[4]; + uint32_t _crtc[4]; + int count; /* 1:1 mapping between crtc:connector */ + int flags; + int pipe; /* primary pipe for vblank */ + unsigned int current_fb_id; + unsigned int fb_width; + unsigned int fb_height; + unsigned int fb_ids[3]; + int bpp, depth; + struct igt_fb fb_info[3]; + + struct event_state flip_state; + struct event_state vblank_state; + /* Overall step between each round */ + int seq_step; + unsigned int pending_events; + int flip_count; +}; + + +static unsigned long gettime_us(void) +{ + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + + return ts.tv_sec * 1000000 + ts.tv_nsec / 1000; +} + +static void emit_dummy_load__bcs(struct test_output *o) +{ + int i, limit; + drm_intel_bo *dummy_bo, *target_bo, *tmp_bo; + struct igt_fb *fb_info = &o->fb_info[o->current_fb_id]; + unsigned pitch = fb_info->stride; + + limit = intel_gen(devid) < 6 ? 500 : 5000; + + dummy_bo = drm_intel_bo_alloc(bufmgr, "dummy_bo", fb_info->size, 4096); + igt_assert(dummy_bo); + target_bo = gem_handle_to_libdrm_bo(bufmgr, drm_fd, "imported", fb_info->gem_handle); + igt_assert(target_bo); + + for (i = 0; i < limit; i++) { + BLIT_COPY_BATCH_START(devid, 0); + OUT_BATCH((3 << 24) | /* 32 bits */ + (0xcc << 16) | /* copy ROP */ + pitch); + OUT_BATCH(0 << 16 | 0); + OUT_BATCH(o->fb_height << 16 | o->fb_width); + OUT_RELOC_FENCED(dummy_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(devid); + OUT_BATCH(0 << 16 | 0); + OUT_BATCH(pitch); + OUT_RELOC_FENCED(target_bo, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(devid); + ADVANCE_BATCH(); + + if (IS_GEN6(devid) || IS_GEN7(devid)) { + BEGIN_BATCH(3); + OUT_BATCH(XY_SETUP_CLIP_BLT_CMD); + OUT_BATCH(0); + OUT_BATCH(0); + ADVANCE_BATCH(); + } + + tmp_bo = dummy_bo; + dummy_bo = target_bo; + target_bo = tmp_bo; + } + intel_batchbuffer_flush(batch); + + drm_intel_bo_unreference(dummy_bo); + drm_intel_bo_unreference(target_bo); +} + +static void emit_fence_stress(struct test_output *o) +{ + const int num_fences = gem_available_fences(drm_fd); + struct igt_fb *fb_info = &o->fb_info[o->current_fb_id]; + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 *exec; + uint32_t buf[2] = { MI_BATCH_BUFFER_END, 0 }; + drm_intel_bo **bo; + int i; + + bo = calloc(sizeof(*bo), num_fences); + exec = calloc(sizeof(*exec), num_fences+1); + for (i = 0; i < num_fences - 1; i++) { + uint32_t tiling = I915_TILING_X; + unsigned long pitch = 0; + bo[i] = drm_intel_bo_alloc_tiled(bufmgr, + "tiled bo", 1024, 1024, 4, + &tiling, &pitch, 0); + exec[i].handle = bo[i]->handle; + exec[i].flags = EXEC_OBJECT_NEEDS_FENCE; + } + exec[i].handle = fb_info->gem_handle; + exec[i].flags = EXEC_OBJECT_NEEDS_FENCE; + exec[++i].handle = gem_create(drm_fd, 4096); + gem_write(drm_fd, exec[i].handle, 0, buf, sizeof(buf)); + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = (uintptr_t)exec; + execbuf.buffer_count = i + 1; + execbuf.batch_len = sizeof(buf); + if (HAS_BLT_RING(intel_get_drm_devid(drm_fd))) + execbuf.flags = I915_EXEC_BLT; + + gem_execbuf(drm_fd, &execbuf); + + gem_close(drm_fd, exec[i].handle); + for (i = 0; i < num_fences - 1; i++) + drm_intel_bo_unreference(bo[i]); + free(bo); + free(exec); +} + +static void emit_dummy_load__rcs(struct test_output *o) +{ + const struct igt_fb *fb_info = &o->fb_info[o->current_fb_id]; + igt_render_copyfunc_t copyfunc; + struct igt_buf sb[2], *src, *dst; + int i, limit; + + copyfunc = igt_get_render_copyfunc(devid); + if (copyfunc == NULL) + return emit_dummy_load__bcs(o); + + limit = intel_gen(devid) < 6 ? 500 : 5000; + + sb[0].bo = drm_intel_bo_alloc(bufmgr, "dummy_bo", fb_info->size, 4096); + igt_assert(sb[0].bo); + sb[0].size = sb[0].bo->size; + sb[0].tiling = I915_TILING_NONE; + sb[0].data = NULL; + sb[0].num_tiles = sb[0].bo->size; + sb[0].stride = 4 * o->fb_width; + + sb[1].bo = gem_handle_to_libdrm_bo(bufmgr, drm_fd, "imported", fb_info->gem_handle); + igt_assert(sb[1].bo); + sb[1].size = sb[1].bo->size; + sb[1].tiling = fb_info->tiling; + sb[1].data = NULL; + sb[1].num_tiles = sb[1].bo->size; + sb[1].stride = fb_info->stride; + + src = &sb[0]; + dst = &sb[1]; + + for (i = 0; i < limit; i++) { + struct igt_buf *tmp; + + copyfunc(batch, NULL, + src, 0, 0, + o->fb_width, o->fb_height, + dst, 0, 0); + + tmp = src; + src = dst; + dst = tmp; + } + intel_batchbuffer_flush(batch); + + drm_intel_bo_unreference(sb[0].bo); + drm_intel_bo_unreference(sb[1].bo); +} + +static void dpms_off_other_outputs(struct test_output *o) +{ + int i, n; + drmModeConnector *connector; + uint32_t connector_id; + + for (i = 0; i < resources->count_connectors; i++) { + connector_id = resources->connectors[i]; + + for (n = 0; n < o->count; n++) { + if (connector_id == o->kconnector[n]->connector_id) + goto next; + } + + connector = drmModeGetConnector(drm_fd, connector_id); + + kmstest_set_connector_dpms(drm_fd, connector, DRM_MODE_DPMS_ON); + kmstest_set_connector_dpms(drm_fd, connector, DRM_MODE_DPMS_OFF); + + drmModeFreeConnector(connector); +next: + ; + } +} + +static void set_dpms(struct test_output *o, int mode) +{ + for (int n = 0; n < o->count; n++) + kmstest_set_connector_dpms(drm_fd, o->kconnector[n], mode); +} + +static void set_flag(unsigned int *v, unsigned int flag) +{ + igt_assert(!(*v & flag)); + *v |= flag; +} + +static void clear_flag(unsigned int *v, unsigned int flag) +{ + igt_assert(*v & flag); + *v &= ~flag; +} + +static int do_page_flip(struct test_output *o, uint32_t fb_id, bool event) +{ + int n, ret = 0; + + o->flip_count = 0; + + for (n = 0; ret == 0 && n < o->count; n++) + ret = drmModePageFlip(drm_fd, o->_crtc[n], fb_id, + event ? DRM_MODE_PAGE_FLIP_EVENT : 0, + event ? (void *)((unsigned long)o | (n==0)) : NULL); + + if (ret == 0 && event) + set_flag(&o->pending_events, EVENT_FLIP); + + return ret; +} + +struct vblank_reply { + unsigned int sequence; + struct timeval ts; +}; + +static int __wait_for_vblank(unsigned int flags, int crtc_idx, + int target_seq, unsigned long ret_data, + struct vblank_reply *reply) +{ + drmVBlank wait_vbl; + int ret; + unsigned crtc_idx_mask; + bool event = !(flags & TEST_VBLANK_BLOCK); + + memset(&wait_vbl, 0, sizeof(wait_vbl)); + + crtc_idx_mask = crtc_idx << DRM_VBLANK_HIGH_CRTC_SHIFT; + igt_assert(!(crtc_idx_mask & ~DRM_VBLANK_HIGH_CRTC_MASK)); + + wait_vbl.request.type = crtc_idx_mask; + if (flags & TEST_VBLANK_ABSOLUTE) + wait_vbl.request.type |= DRM_VBLANK_ABSOLUTE; + else + wait_vbl.request.type |= DRM_VBLANK_RELATIVE; + if (event) { + wait_vbl.request.type |= DRM_VBLANK_EVENT; + wait_vbl.request.signal = ret_data; + } + wait_vbl.request.sequence = target_seq; + + ret = drmWaitVBlank(drm_fd, &wait_vbl); + + if (ret == 0) { + reply->ts.tv_sec = wait_vbl.reply.tval_sec; + reply->ts.tv_usec = wait_vbl.reply.tval_usec; + reply->sequence = wait_vbl.reply.sequence; + } else + ret = -errno; + + return ret; +} + +static int do_wait_for_vblank(struct test_output *o, int pipe_id, + int target_seq, struct vblank_reply *reply) +{ + int ret; + unsigned flags = o->flags; + + /* Absolute waits only works once we have a frame counter. */ + if (!(o->vblank_state.count > 0)) + flags &= ~TEST_VBLANK_ABSOLUTE; + + ret = __wait_for_vblank(flags, pipe_id, target_seq, (unsigned long)o, + reply); + if (ret == 0 && !(o->flags & TEST_VBLANK_BLOCK)) + set_flag(&o->pending_events, EVENT_VBLANK); + + return ret; +} + +static bool +analog_tv_connector(struct test_output *o) +{ + uint32_t connector_type = o->kconnector[0]->connector_type; + + return connector_type == DRM_MODE_CONNECTOR_TV || + connector_type == DRM_MODE_CONNECTOR_9PinDIN || + connector_type == DRM_MODE_CONNECTOR_SVIDEO || + connector_type == DRM_MODE_CONNECTOR_Composite; +} + +static void event_handler(struct event_state *es, unsigned int frame, + unsigned int sec, unsigned int usec) +{ + struct timeval now; + + if (monotonic_timestamp) { + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + now.tv_sec = ts.tv_sec; + now.tv_usec = ts.tv_nsec / 1000; + } else { + gettimeofday(&now, NULL); + } + es->current_received_ts = now; + + es->current_ts.tv_sec = sec; + es->current_ts.tv_usec = usec; + es->current_seq = frame; +} + +static void page_flip_handler(int fd, unsigned int frame, unsigned int sec, + unsigned int usec, void *data) +{ + int primary = (unsigned long)data & 1; + struct test_output *o = (void *)((unsigned long)data & ~ 1); + + if (++o->flip_count == o->count) + clear_flag(&o->pending_events, EVENT_FLIP); + if (primary) + event_handler(&o->flip_state, frame, sec, usec); +} + +static double frame_time(struct test_output *o) +{ + return 1000.0 * 1000.0 / o->kmode[0].vrefresh; +} + +static void *vblank_wait_thread_func(void *data) +{ + struct test_output *o = data; + struct vblank_reply reply; + int i; + + for (i = 0; i < 32; i++) { + unsigned long start = gettime_us(); + __wait_for_vblank(TEST_VBLANK_BLOCK, o->pipe, 20, (unsigned long)o, &reply); + if (gettime_us() - start > 2 * frame_time(o)) + return (void*)1; + } + + return 0; +} + +static void spawn_vblank_wait_thread(struct test_output *o) +{ + igt_assert(pthread_create(&vblank_wait_thread, NULL, + vblank_wait_thread_func, o) == 0); +} + +static void join_vblank_wait_thread(void) +{ + igt_assert(pthread_join(vblank_wait_thread, NULL) == 0); +} + +static void fixup_premature_vblank_ts(struct test_output *o, + struct event_state *es) +{ + /* + * In case a power off event preempts the completion of a + * wait-for-vblank event the kernel will return a wf-vblank event with + * a zeroed-out timestamp. In order that check_state() doesn't + * complain replace this ts with a valid ts. As we can't calculate the + * exact timestamp, just use the time we received the event. + */ + struct timeval tv; + + if (!(o->flags & (TEST_DPMS | TEST_MODESET))) + return; + + if (o->vblank_state.current_ts.tv_sec != 0 || + o->vblank_state.current_ts.tv_usec != 0) + return; + + tv.tv_sec = 0; + tv.tv_usec = 1; + timersub(&es->current_received_ts, &tv, &es->current_ts); +} + +static void vblank_handler(int fd, unsigned int frame, unsigned int sec, + unsigned int usec, void *data) +{ + struct test_output *o = data; + + clear_flag(&o->pending_events, EVENT_VBLANK); + event_handler(&o->vblank_state, frame, sec, usec); + fixup_premature_vblank_ts(o, &o->vblank_state); +} + +static void check_state(struct test_output *o, struct event_state *es) +{ + struct timeval diff; + double usec_interflip; + + timersub(&es->current_ts, &es->current_received_ts, &diff); + if (!analog_tv_connector(o)) { + igt_assert_f(diff.tv_sec < 0 || (diff.tv_sec == 0 && diff.tv_usec <= 2000), + "%s ts delayed for too long: %is, %iusec\n", + es->name, (int)diff.tv_sec, (int)diff.tv_usec); + + } + + if (es->count == 0) + return; + + timersub(&es->current_ts, &es->last_received_ts, &diff); + igt_assert_f(timercmp(&es->last_received_ts, &es->current_ts, <), + "%s ts before the %s was issued!\n" + "timerdiff %is, %ius\n", + es->name, es->name, + (int) diff.tv_sec, (int) diff.tv_usec); + + /* check only valid if no modeset happens in between, that increments by + * (1 << 23) on each step. This bounding matches the one in + * DRM_IOCTL_WAIT_VBLANK. */ + if (!(o->flags & (TEST_DPMS | TEST_MODESET))) + igt_assert_f(es->current_seq - (es->last_seq + o->seq_step) <= 1UL << 23, + "unexpected %s seq %u, should be >= %u\n", + es->name, es->current_seq, es->last_seq + o->seq_step); + + /* Check that the vblank frame didn't wrap unexpectedly. */ + if (o->flags & TEST_TS_CONT) { + /* Ignore seq_step here since vblank waits time out immediately + * when we kill the crtc. */ + igt_assert_f(es->current_seq - es->last_seq >= 0, + "unexpected %s seq %u, should be >= %u\n", + es->name, es->current_seq, es->last_seq); + igt_assert_f(es->current_seq - es->last_seq <= 100, + "unexpected %s seq %u, should be < %u\n", + es->name, es->current_seq, es->last_seq + 100); + + igt_debug("testing ts continuity: Current frame %u, old frame %u\n", + es->current_seq, es->last_seq); + } + + if ((o->flags & TEST_CHECK_TS) && (!analog_tv_connector(o))) { + timersub(&es->current_ts, &es->last_ts, &diff); + usec_interflip = (double)o->seq_step * frame_time(o); + + igt_assert_f(fabs((((double) diff.tv_usec) - usec_interflip) / + usec_interflip) <= 0.005, + "inter-%s ts jitter: %is, %ius\n", + es->name, (int) diff.tv_sec, (int) diff.tv_usec); + + igt_assert_f(es->current_seq == es->last_seq + o->seq_step, + "unexpected %s seq %u, expected %u\n", + es->name, es->current_seq, + es->last_seq + o->seq_step); + } +} + +static void check_state_correlation(struct test_output *o, + struct event_state *es1, + struct event_state *es2) +{ + struct timeval tv_diff; + double ftime; + double usec_diff; + int seq_diff; + + if (es1->count == 0 || es2->count == 0) + return; + + timersub(&es2->current_ts, &es1->current_ts, &tv_diff); + usec_diff = tv_diff.tv_sec * 1000 * 1000 + tv_diff.tv_usec; + + seq_diff = es2->current_seq - es1->current_seq; + ftime = frame_time(o); + usec_diff -= seq_diff * ftime; + + igt_assert_f(fabs(usec_diff) / ftime <= 0.005, + "timestamp mismatch between %s and %s (diff %.4f sec)\n", + es1->name, es2->name, usec_diff / 1000 / 1000); +} + +static void check_all_state(struct test_output *o, + unsigned int completed_events) +{ + bool flip, vblank; + + flip = completed_events & EVENT_FLIP; + vblank = completed_events & EVENT_VBLANK; + + if (flip) + check_state(o, &o->flip_state); + if (vblank) + check_state(o, &o->vblank_state); + + /* FIXME: Correlation check is broken. */ + if (flip && vblank && 0) + check_state_correlation(o, &o->flip_state, &o->vblank_state); +} + +static void recreate_fb(struct test_output *o) +{ + drmModeFBPtr r; + struct igt_fb *fb_info = &o->fb_info[o->current_fb_id]; + uint32_t new_fb_id; + + /* Call rmfb/getfb/addfb to ensure those don't introduce stalls */ + r = drmModeGetFB(drm_fd, fb_info->fb_id); + igt_assert(r); + + do_or_die(drmModeAddFB(drm_fd, o->fb_width, o->fb_height, o->depth, + o->bpp, fb_info->stride, + r->handle, &new_fb_id)); + + gem_close(drm_fd, r->handle); + drmFree(r); + do_or_die(drmModeRmFB(drm_fd, fb_info->fb_id)); + + o->fb_ids[o->current_fb_id] = new_fb_id; + o->fb_info[o->current_fb_id].fb_id = new_fb_id; +} + +static void set_y_tiling(struct test_output *o, int fb_idx) +{ + drmModeFBPtr r; + struct igt_fb *fb_info = &o->fb_info[fb_idx]; + + /* Call rmfb/getfb/addfb to ensure those don't introduce stalls */ + r = drmModeGetFB(drm_fd, fb_info->fb_id); + igt_assert(r); + /* Newer kernels don't allow such shenagians any more, so skip the test. */ + igt_require(__gem_set_tiling(drm_fd, r->handle, I915_TILING_Y, fb_info->stride) == 0); + gem_close(drm_fd, r->handle); + drmFree(r); +} + +static void stop_rings(bool stop) +{ + if (stop) + igt_set_stop_rings(STOP_RING_DEFAULTS); + else + igt_set_stop_rings(STOP_RING_NONE); +} + +static void eat_error_state(void) +{ + static const char dfs_base[] = "/sys/kernel/debug/dri"; + static const char dfs_entry_error[] = "i915_error_state"; + static const char data[] = ""; + char fname[FILENAME_MAX]; + int card_index = drm_get_card(); + int fd; + + igt_assert(card_index != -1); + + /* clear the error state */ + snprintf(fname, FILENAME_MAX, "%s/%i/%s", + dfs_base, card_index, dfs_entry_error); + + fd = open(fname, O_WRONLY); + igt_assert(fd >= 0); + + igt_assert(write(fd, data, sizeof(data)) == sizeof(data)); + close(fd); + + /* and check whether stop_rings is not reset, i.e. the hang has indeed + * happened */ + igt_assert_f(igt_get_stop_rings() == STOP_RING_NONE, + "no gpu hang detected, stop_rings is still 0x%x\n", + igt_get_stop_rings()); + + close(fd); +} + +static void unhang_gpu(int fd, uint32_t handle) +{ + gem_sync(drm_fd, handle); + gem_close(drm_fd, handle); + eat_error_state(); + stop_rings(false); +} + +static uint32_t hang_gpu(int fd) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 gem_exec; + uint32_t b[2] = {MI_BATCH_BUFFER_END}; + + stop_rings(true); + + memset(&gem_exec, 0, sizeof(gem_exec)); + gem_exec.handle = gem_create(fd, 4096); + gem_write(fd, gem_exec.handle, 0, b, sizeof(b)); + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = (uintptr_t)&gem_exec; + execbuf.buffer_count = 1; + execbuf.batch_len = sizeof(b); + + if (drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf)) { + igt_assert_f(errno == EIO, + "failed to exercise page flip hang recovery\n"); + + unhang_gpu(fd, gem_exec.handle); + gem_exec.handle = 0; + } + + return gem_exec.handle; +} + +static bool is_hung(int fd) +{ + if (drmIoctl(fd, DRM_IOCTL_I915_GEM_THROTTLE, 0) == 0) + return false; + + return errno == EIO; +} + +static int set_mode(struct test_output *o, uint32_t fb, int x, int y) +{ + int n; + + for (n = 0; n < o->count; n++) { + if (fb == 0) { + int ret = drmModeSetCrtc(drm_fd, o->_crtc[n], + 0, 0, 0, + 0, 0, 0); + if (ret) + return ret; + } else { + int ret = drmModeSetCrtc(drm_fd, o->_crtc[n], + fb, x, y, + &o->_connector[n], 1, &o->kmode[n]); + if (ret) + return ret; + } + } + + return 0; +} + +/* Return mask of completed events. */ +static unsigned int run_test_step(struct test_output *o) +{ + unsigned int new_fb_id; + /* for funny reasons page_flip returns -EBUSY on disabled crtcs ... */ + int expected_einval = o->flags & TEST_MODESET ? -EBUSY : -EINVAL; + unsigned int completed_events = 0; + bool do_flip; + bool do_vblank; + struct vblank_reply vbl_reply; + unsigned int target_seq; + uint32_t hang = 0; /* Suppress GCC warning */ + + target_seq = o->vblank_state.seq_step; + /* Absolute waits only works once we have a frame counter. */ + if (o->flags & TEST_VBLANK_ABSOLUTE && o->vblank_state.count > 0) + target_seq += o->vblank_state.last_seq; + + /* + * It's possible that we don't have a pending flip here, in case both + * wf-vblank and flip were scheduled and the wf-vblank event was + * delivered earlier. The same applies to vblank events w.r.t flip. + */ + do_flip = (o->flags & TEST_FLIP) && !(o->pending_events & EVENT_FLIP); + do_vblank = (o->flags & TEST_VBLANK) && + !(o->pending_events & EVENT_VBLANK); + + if (o->flags & TEST_DPMS_OFF_OTHERS) + dpms_off_other_outputs(o); + + if (o->flags & TEST_WITH_DUMMY_BCS) + emit_dummy_load__bcs(o); + + if (o->flags & TEST_WITH_DUMMY_RCS) + emit_dummy_load__rcs(o); + + if (!(o->flags & TEST_SINGLE_BUFFER)) + o->current_fb_id = !o->current_fb_id; + + if (o->flags & TEST_FB_RECREATE) + recreate_fb(o); + new_fb_id = o->fb_ids[o->current_fb_id]; + + if (o->flags & TEST_FB_BAD_TILING) + new_fb_id = o->fb_ids[2]; + + if ((o->flags & TEST_VBLANK_EXPIRED_SEQ) && + !(o->pending_events & EVENT_VBLANK) && o->flip_state.count > 0) { + struct vblank_reply reply; + unsigned int exp_seq; + unsigned long start; + + exp_seq = o->flip_state.current_seq; + start = gettime_us(); + do_or_die(__wait_for_vblank(TEST_VBLANK_ABSOLUTE | + TEST_VBLANK_BLOCK, o->pipe, exp_seq, + 0, &reply)); + igt_assert(gettime_us() - start < 500); + igt_assert(reply.sequence == exp_seq); + igt_assert(timercmp(&reply.ts, &o->flip_state.last_ts, ==)); + } + + if (o->flags & TEST_ENOENT) { + /* hope that fb 0xfffffff0 does not exist */ + igt_assert(do_page_flip(o, 0xfffffff0, false) == -ENOENT); + igt_assert(set_mode(o, 0xfffffff0, 0, 0) == -ENOENT); + } + + if (do_flip && (o->flags & TEST_EINVAL) && o->flip_state.count > 0) + igt_assert(do_page_flip(o, new_fb_id, true) == expected_einval); + + if (o->flags & TEST_FB_BAD_TILING) + new_fb_id = o->fb_ids[o->current_fb_id]; + + if (do_vblank && (o->flags & TEST_EINVAL) && o->vblank_state.count > 0) + igt_assert(do_wait_for_vblank(o, o->pipe, target_seq, &vbl_reply) + == -EINVAL); + + if (o->flags & TEST_VBLANK_RACE) { + spawn_vblank_wait_thread(o); + + if (o->flags & TEST_MODESET) + igt_assert_f(set_mode(o, 0 /* no fb */, 0, 0) == 0, + "failed to disable output: %s\n", + strerror(errno)); + } + + if (o->flags & TEST_DPMS_OFF) + set_dpms(o, DRM_MODE_DPMS_OFF); + + if (o->flags & TEST_MODESET) + igt_assert(set_mode(o, o->fb_ids[o->current_fb_id], 0, 0) == 0); + + if (o->flags & TEST_DPMS) + set_dpms(o, DRM_MODE_DPMS_ON); + + if (o->flags & TEST_VBLANK_RACE) { + struct vblank_reply reply; + unsigned long start, end; + + /* modeset/DPMS is done, vblank wait should work normally now */ + start = gettime_us(); + igt_assert(__wait_for_vblank(TEST_VBLANK_BLOCK, o->pipe, 1, 0, &reply) == 0); + end = gettime_us(); + igt_assert(end - start > 1 * frame_time(o) / 2 && + end - start < 3 * frame_time(o) / 2); + join_vblank_wait_thread(); + } + + igt_info("."); fflush(stdout); + + if (do_flip && (o->flags & TEST_HANG)) { + hang = hang_gpu(drm_fd); + igt_assert_f(hang, "failed to exercise page flip hang recovery\n"); + } + + /* try to make sure we can issue two flips during the same frame */ + if (do_flip && (o->flags & TEST_EBUSY)) { + struct vblank_reply reply; + igt_assert(__wait_for_vblank(TEST_VBLANK_BLOCK, o->pipe, 1, 0, &reply) == 0); + } + + if (do_flip) + do_or_die(do_page_flip(o, new_fb_id, !(o->flags & TEST_NOEVENT))); + + if (o->flags & TEST_FENCE_STRESS) + emit_fence_stress(o); + + if (do_vblank) { + do_or_die(do_wait_for_vblank(o, o->pipe, target_seq, + &vbl_reply)); + if (o->flags & TEST_VBLANK_BLOCK) { + event_handler(&o->vblank_state, vbl_reply.sequence, + vbl_reply.ts.tv_sec, + vbl_reply.ts.tv_usec); + completed_events = EVENT_VBLANK; + } + } + + if (do_flip && (o->flags & TEST_EBUSY)) + igt_assert(do_page_flip(o, new_fb_id, true) == -EBUSY); + + if (do_flip && (o->flags & TEST_RMFB)) + recreate_fb(o); + + /* pan before the flip completes */ + if (o->flags & TEST_PAN) { + int count = do_flip ? + o->flip_state.count : o->vblank_state.count; + int x_ofs = count * 10 > o->fb_width - o->kmode[0].hdisplay ? o->fb_width - o->kmode[0].hdisplay : count * 10; + + /* Make sure DSPSURF changes value */ + if (o->flags & TEST_HANG) + o->current_fb_id = !o->current_fb_id; + + igt_assert_f(set_mode(o, o->fb_ids[o->current_fb_id], x_ofs, 0) == 0, + "failed to pan (%dx%d@%dHz)+%d: %s\n", + o->kmode[0].hdisplay, o->kmode[0].vdisplay, o->kmode[0].vrefresh, + x_ofs, strerror(errno)); + } + + if (o->flags & TEST_DPMS) + set_dpms(o, DRM_MODE_DPMS_OFF); + + if (o->flags & TEST_MODESET && !(o->flags & TEST_RMFB) && !(o->flags & TEST_VBLANK_RACE)) + igt_assert_f(set_mode(o, 0 /* no fb */, 0, 0) == 0, + "failed to disable output: %s\n", + strerror(errno)); + + if (o->flags & TEST_RPM) + igt_assert(igt_wait_for_pm_status(IGT_RUNTIME_PM_STATUS_SUSPENDED)); + + if (o->flags & TEST_SUSPEND) + igt_system_suspend_autoresume(); + + if (do_vblank && (o->flags & TEST_EINVAL) && o->vblank_state.count > 0) + igt_assert(do_wait_for_vblank(o, o->pipe, target_seq, &vbl_reply) + == -EINVAL); + + if (do_flip && (o->flags & TEST_EINVAL) && !(o->flags & TEST_FB_BAD_TILING)) + igt_assert(do_page_flip(o, new_fb_id, true) == expected_einval); + + if (hang) + unhang_gpu(drm_fd, hang); + + return completed_events; +} + +static void update_state(struct event_state *es) +{ + es->last_received_ts = es->current_received_ts; + es->last_ts = es->current_ts; + es->last_seq = es->current_seq; + es->count++; +} + +static void update_all_state(struct test_output *o, + unsigned int completed_events) +{ + if (completed_events & EVENT_FLIP) + update_state(&o->flip_state); + + if (completed_events & EVENT_VBLANK) + update_state(&o->vblank_state); +} + +static void connector_find_preferred_mode(uint32_t connector_id, int crtc_idx, + struct test_output *o) +{ + struct kmstest_connector_config config; + + if (kmstest_get_connector_config(drm_fd, connector_id, 1 << crtc_idx, + &config) < 0) { + o->mode_valid = 0; + return; + } + + o->pipe = config.pipe; + o->kconnector[0] = config.connector; + o->kencoder[0] = config.encoder; + o->_crtc[0] = config.crtc->crtc_id; + o->kmode[0] = config.default_mode; + o->mode_valid = 1; + + o->fb_width = o->kmode[0].hdisplay; + o->fb_height = o->kmode[0].vdisplay; + + drmModeFreeCrtc(config.crtc); +} + +static bool mode_compatible(const drmModeModeInfo *a, const drmModeModeInfo *b) +{ + int d_refresh; + + if (a->hdisplay != b->hdisplay) + return false; + + if (a->vdisplay != b->vdisplay) + return false; + + d_refresh = a->vrefresh - b->vrefresh; + if (d_refresh < -1 || d_refresh > 1) + return false; + + return true; +} + +static void connector_find_compatible_mode(int crtc_idx0, int crtc_idx1, + struct test_output *o) +{ + struct kmstest_connector_config config[2]; + drmModeModeInfo *mode[2]; + int n, m; + + if (kmstest_get_connector_config(drm_fd, o->_connector[0], + 1 << crtc_idx0, &config[0]) < 0) + return; + + if (kmstest_get_connector_config(drm_fd, o->_connector[1], + 1 << crtc_idx1, &config[1]) < 0) { + kmstest_free_connector_config(&config[0]); + return; + } + + mode[0] = &config[0].default_mode; + mode[1] = &config[1].default_mode; + if (!mode_compatible(mode[0], mode[1])) { + for (n = 0; n < config[0].connector->count_modes; n++) { + mode[0] = &config[0].connector->modes[n]; + for (m = 0; m < config[1].connector->count_modes; m++) { + mode[1] = &config[1].connector->modes[m]; + if (mode_compatible(mode[0], mode[1])) + goto found; + } + } + + /* hope for the best! */ + mode[1] = mode[0] = &config[0].default_mode; + } + +found: + o->pipe = config[0].pipe; + o->fb_width = mode[0]->hdisplay; + o->fb_height = mode[0]->vdisplay; + o->mode_valid = 1; + + o->kconnector[0] = config[0].connector; + o->kencoder[0] = config[0].encoder; + o->_crtc[0] = config[0].crtc->crtc_id; + o->kmode[0] = *mode[0]; + + o->kconnector[1] = config[1].connector; + o->kencoder[1] = config[1].encoder; + o->_crtc[1] = config[1].crtc->crtc_id; + o->kmode[1] = *mode[1]; + + drmModeFreeCrtc(config[0].crtc); + drmModeFreeCrtc(config[1].crtc); +} + +static void paint_flip_mode(struct igt_fb *fb, bool odd_frame) +{ + cairo_t *cr = igt_get_cairo_ctx(drm_fd, fb); + int width = fb->width; + int height = fb->height; + + igt_paint_test_pattern(cr, width, height); + + if (odd_frame) + cairo_rectangle(cr, width/4, height/2, width/4, height/8); + else + cairo_rectangle(cr, width/2, height/2, width/4, height/8); + + cairo_set_source_rgb(cr, 1, 1, 1); + cairo_fill(cr); + + igt_assert(!cairo_status(cr)); + cairo_destroy(cr); +} + +static int +fb_is_bound(struct test_output *o, int fb) +{ + int n; + + for (n = 0; n < o->count; n++) { + struct drm_mode_crtc mode; + + mode.crtc_id = o->_crtc[n]; + if (drmIoctl(drm_fd, DRM_IOCTL_MODE_GETCRTC, &mode)) + return 0; + + if (!mode.mode_valid || mode.fb_id != fb) + return false; + } + + return true; +} + +static void check_final_state(struct test_output *o, struct event_state *es, + unsigned int elapsed) +{ + igt_assert_f(es->count > 0, + "no %s event received\n", es->name); + + /* Verify we drop no frames, but only if it's not a TV encoder, since + * those use some funny fake timings behind userspace's back. */ + if (o->flags & TEST_CHECK_TS && !analog_tv_connector(o)) { + int expected; + int count = es->count; + + count *= o->seq_step; + expected = elapsed * o->kmode[0].vrefresh / (1000 * 1000); + igt_assert_f(count >= expected * 99/100 && count <= expected * 101/100, + "dropped frames, expected %d, counted %d, encoder type %d\n", + expected, count, o->kencoder[0]->encoder_type); + } +} + +/* + * Wait until at least one pending event completes. Return mask of completed + * events. + */ +static unsigned int wait_for_events(struct test_output *o) +{ + drmEventContext evctx; + struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 }; + fd_set fds; + unsigned int event_mask; + int ret; + + event_mask = o->pending_events; + igt_assert(event_mask); + + memset(&evctx, 0, sizeof evctx); + evctx.version = DRM_EVENT_CONTEXT_VERSION; + evctx.vblank_handler = vblank_handler; + evctx.page_flip_handler = page_flip_handler; + + /* make timeout lax with the dummy load */ + if (o->flags & (TEST_WITH_DUMMY_BCS | TEST_WITH_DUMMY_RCS)) + timeout.tv_sec *= 60; + + FD_ZERO(&fds); + FD_SET(drm_fd, &fds); + do { + do { + ret = select(drm_fd + 1, &fds, NULL, NULL, &timeout); + } while (ret < 0 && errno == EINTR); + + igt_assert_f(ret >= 0, + "select error (errno %i)\n", errno); + igt_assert_f(ret > 0, + "select timed out or error (ret %d)\n", ret); + igt_assert_f(!FD_ISSET(0, &fds), + "no fds active, breaking\n"); + + do_or_die(drmHandleEvent(drm_fd, &evctx)); + } while (o->pending_events); + + event_mask ^= o->pending_events; + igt_assert(event_mask); + + return event_mask; +} + +/* Returned the elapsed time in us */ +static unsigned event_loop(struct test_output *o, unsigned duration_ms) +{ + unsigned long start, end; + uint32_t hang = 0; /* Suppress GCC warning */ + int count = 0; + + if (o->flags & TEST_HANG_ONCE) { + hang = hang_gpu(drm_fd); + igt_assert_f(hang, "failed to exercise page flip hang recovery\n"); + } + + start = gettime_us(); + + while (1) { + unsigned int completed_events; + + completed_events = run_test_step(o); + if (o->pending_events) + completed_events |= wait_for_events(o); + check_all_state(o, completed_events); + update_all_state(o, completed_events); + + if (count && (gettime_us() - start) / 1000 >= duration_ms) + break; + + count++; + } + + end = gettime_us(); + + if (hang) + unhang_gpu(drm_fd, hang); + + /* Flush any remaining events */ + if (o->pending_events) + wait_for_events(o); + + return end - start; +} + +static void free_test_output(struct test_output *o) +{ + int i; + + for (i = 0; i < o->count; i++) { + drmModeFreeEncoder(o->kencoder[i]); + drmModeFreeConnector(o->kconnector[i]); + } +} + +static void run_test_on_crtc_set(struct test_output *o, int *crtc_idxs, + int crtc_count, int duration_ms) +{ + char test_name[128]; + unsigned elapsed; + unsigned bo_size = 0; + bool tiled; + int i; + + switch (crtc_count) { + case 1: + connector_find_preferred_mode(o->_connector[0], crtc_idxs[0], o); + snprintf(test_name, sizeof(test_name), + "%s on crtc %d, connector %d", + igt_subtest_name(), o->_crtc[0], o->_connector[0]); + break; + case 2: + connector_find_compatible_mode(crtc_idxs[0], crtc_idxs[1], o); + snprintf(test_name, sizeof(test_name), + "%s on crtc %d:%d, connector %d:%d", + igt_subtest_name(), o->_crtc[0], o->_crtc[1], + o->_connector[0], o->_connector[1]); + break; + default: + igt_assert(0); + } + if (!o->mode_valid) + return; + + igt_assert(o->count == crtc_count); + + last_connector = o->kconnector[0]; + + igt_info("Beginning %s\n", test_name); + + if (o->flags & TEST_PAN) + o->fb_width *= 2; + + tiled = false; + if (o->flags & TEST_FENCE_STRESS) + tiled = true; + + /* 256 MB is usually the maximum mappable aperture, + * (make it 4x times that to ensure failure) */ + if (o->flags & TEST_BO_TOOBIG) + bo_size = 4*256*1024*1024; + + o->fb_ids[0] = igt_create_fb(drm_fd, o->fb_width, o->fb_height, + igt_bpp_depth_to_drm_format(o->bpp, o->depth), + tiled, &o->fb_info[0]); + o->fb_ids[1] = igt_create_fb_with_bo_size(drm_fd, o->fb_width, o->fb_height, + igt_bpp_depth_to_drm_format(o->bpp, o->depth), + tiled, &o->fb_info[1], bo_size); + o->fb_ids[2] = igt_create_fb(drm_fd, o->fb_width, o->fb_height, + igt_bpp_depth_to_drm_format(o->bpp, o->depth), + true, &o->fb_info[2]); + igt_assert(o->fb_ids[0]); + igt_assert(o->fb_ids[1]); + if (o->flags & TEST_FB_BAD_TILING) + igt_require(o->fb_ids[2]); + + paint_flip_mode(&o->fb_info[0], false); + if (!(o->flags & TEST_BO_TOOBIG)) + paint_flip_mode(&o->fb_info[1], true); + if (o->fb_ids[2]) + paint_flip_mode(&o->fb_info[2], true); + + if (o->flags & TEST_FB_BAD_TILING) + set_y_tiling(o, 2); + + for (i = 0; i < o->count; i++) + kmstest_dump_mode(&o->kmode[i]); + + if (set_mode(o, o->fb_ids[0], 0, 0)) { + /* We may fail to apply the mode if there are hidden + * constraints, such as bandwidth on the third pipe. + */ + igt_assert_f(crtc_count > 1 || crtc_idxs[0] < 2, + "set_mode may only fail on the 3rd pipe or in multiple crtc tests\n"); + goto out; + } + igt_assert(fb_is_bound(o, o->fb_ids[0])); + + /* quiescent the hw a bit so ensure we don't miss a single frame */ + if (o->flags & TEST_CHECK_TS) + sleep(1); + + if (o->flags & TEST_BO_TOOBIG) { + igt_assert(do_page_flip(o, o->fb_ids[1], true) == -E2BIG); + goto out; + } else + igt_assert(do_page_flip(o, o->fb_ids[1], true) == 0); + wait_for_events(o); + + o->current_fb_id = 1; + + if (o->flags & TEST_FLIP) + o->flip_state.seq_step = 1; + else + o->flip_state.seq_step = 0; + if (o->flags & TEST_VBLANK) + o->vblank_state.seq_step = 10; + else + o->vblank_state.seq_step = 0; + + /* We run the vblank and flip actions in parallel by default. */ + o->seq_step = max(o->vblank_state.seq_step, o->flip_state.seq_step); + + elapsed = event_loop(o, duration_ms); + + if (o->flags & TEST_FLIP && !(o->flags & TEST_NOEVENT)) + check_final_state(o, &o->flip_state, elapsed); + if (o->flags & TEST_VBLANK) + check_final_state(o, &o->vblank_state, elapsed); + + igt_info("\n%s: PASSED\n\n", test_name); + +out: + if (o->fb_ids[2]) + igt_remove_fb(drm_fd, &o->fb_info[2]); + igt_remove_fb(drm_fd, &o->fb_info[1]); + igt_remove_fb(drm_fd, &o->fb_info[0]); + + last_connector = NULL; + + free_test_output(o); +} + +static int run_test(int duration, int flags) +{ + struct test_output o; + int i, n, modes = 0; + + igt_require((flags & TEST_HANG) == 0 || !is_hung(drm_fd)); + + + if (flags & TEST_RPM) + igt_require(igt_setup_runtime_pm()); + + resources = drmModeGetResources(drm_fd); + igt_assert(resources); + + /* Count output configurations to scale test runtime. */ + for (i = 0; i < resources->count_connectors; i++) { + for (n = 0; n < resources->count_crtcs; n++) { + memset(&o, 0, sizeof(o)); + o.count = 1; + o._connector[0] = resources->connectors[i]; + o.flags = flags; + o.flip_state.name = "flip"; + o.vblank_state.name = "vblank"; + o.bpp = 32; + o.depth = 24; + + connector_find_preferred_mode(o._connector[0], n, &o); + if (o.mode_valid) + modes++; + + free_test_output(&o); + } + } + + igt_assert(modes); + duration = duration * 1000 / modes; + duration = duration < 500 ? 500 : duration; + + /* Find any connected displays */ + for (i = 0; i < resources->count_connectors; i++) { + for (n = 0; n < resources->count_crtcs; n++) { + int crtc_idx; + + memset(&o, 0, sizeof(o)); + o.count = 1; + o._connector[0] = resources->connectors[i]; + o.flags = flags; + o.flip_state.name = "flip"; + o.vblank_state.name = "vblank"; + o.bpp = 32; + o.depth = 24; + + crtc_idx = n; + run_test_on_crtc_set(&o, &crtc_idx, 1, duration); + } + } + + drmModeFreeResources(resources); + return 1; +} + +static int run_pair(int duration, int flags) +{ + struct test_output o; + int i, j, m, n, modes = 0; + + igt_require((flags & TEST_HANG) == 0 || !is_hung(drm_fd)); + + resources = drmModeGetResources(drm_fd); + igt_assert(resources); + + /* Find a pair of connected displays */ + for (i = 0; i < resources->count_connectors; i++) { + for (n = 0; n < resources->count_crtcs; n++) { + for (j = i + 1; j < resources->count_connectors; j++) { + for (m = n + 1; m < resources->count_crtcs; m++) { + memset(&o, 0, sizeof(o)); + o.count = 2; + o._connector[0] = resources->connectors[i]; + o._connector[1] = resources->connectors[j]; + o.flags = flags; + o.flip_state.name = "flip"; + o.vblank_state.name = "vblank"; + o.bpp = 32; + o.depth = 24; + + connector_find_compatible_mode(n, m, &o); + if (o.mode_valid) + modes++; + + free_test_output(&o); + } + } + } + } + + /* If we have fewer than 2 connected outputs then we won't have any + * configuration at all. So skip in that case. */ + igt_require(modes); + duration = duration * 1000 / modes; + duration = duration < 500 ? 500 : duration; + + /* Find a pair of connected displays */ + for (i = 0; i < resources->count_connectors; i++) { + for (n = 0; n < resources->count_crtcs; n++) { + for (j = i + 1; j < resources->count_connectors; j++) { + for (m = n + 1; m < resources->count_crtcs; m++) { + int crtc_idxs[2]; + + memset(&o, 0, sizeof(o)); + o.count = 2; + o._connector[0] = resources->connectors[i]; + o._connector[1] = resources->connectors[j]; + o.flags = flags; + o.flip_state.name = "flip"; + o.vblank_state.name = "vblank"; + o.bpp = 32; + o.depth = 24; + + crtc_idxs[0] = n; + crtc_idxs[1] = m; + + run_test_on_crtc_set(&o, crtc_idxs, 2, + duration); + } + } + } + } + + drmModeFreeResources(resources); + return 1; +} + +static void get_timestamp_format(void) +{ + uint64_t cap_mono; + int ret; + + ret = drmGetCap(drm_fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap_mono); + igt_assert(ret == 0 || errno == EINVAL); + monotonic_timestamp = ret == 0 && cap_mono == 1; + igt_info("Using %s timestamps\n", + monotonic_timestamp ? "monotonic" : "real"); +} + +static void kms_flip_exit_handler(int sig) +{ + igt_fixture { + if (last_connector) + kmstest_set_connector_dpms(drm_fd, last_connector, DRM_MODE_DPMS_ON); + } +} + +int main(int argc, char **argv) +{ + struct { + int duration; + int flags; + const char *name; + } tests[] = { + { 30, TEST_VBLANK, "wf_vblank" }, + { 30, TEST_VBLANK | TEST_CHECK_TS, "wf_vblank-ts-check" }, + { 30, TEST_VBLANK | TEST_VBLANK_BLOCK | TEST_CHECK_TS, + "blocking-wf_vblank" }, + { 30, TEST_VBLANK | TEST_VBLANK_ABSOLUTE, + "absolute-wf_vblank" }, + { 30, TEST_VBLANK | TEST_VBLANK_BLOCK | TEST_VBLANK_ABSOLUTE, + "blocking-absolute-wf_vblank" }, + { 60, TEST_VBLANK | TEST_DPMS | TEST_EINVAL, "wf_vblank-vs-dpms" }, + { 60, TEST_VBLANK | TEST_DPMS | TEST_WITH_DUMMY_BCS, + "bcs-wf_vblank-vs-dpms" }, + { 60, TEST_VBLANK | TEST_DPMS | TEST_WITH_DUMMY_RCS, + "rcs-wf_vblank-vs-dpms" }, + { 60, TEST_VBLANK | TEST_MODESET | TEST_EINVAL, "wf_vblank-vs-modeset" }, + { 60, TEST_VBLANK | TEST_MODESET | TEST_WITH_DUMMY_BCS, + "bcs-wf_vblank-vs-modeset" }, + { 60, TEST_VBLANK | TEST_MODESET | TEST_WITH_DUMMY_RCS, + "rcs-wf_vblank-vs-modeset" }, + + { 30, TEST_FLIP , "plain-flip" }, + { 30, TEST_FLIP | TEST_EBUSY , "busy-flip" }, + { 30, TEST_FLIP | TEST_FENCE_STRESS , "flip-vs-fences" }, + { 30, TEST_FLIP | TEST_CHECK_TS, "plain-flip-ts-check" }, + { 30, TEST_FLIP | TEST_CHECK_TS | TEST_FB_RECREATE, + "plain-flip-fb-recreate" }, + { 30, TEST_FLIP | TEST_RMFB | TEST_MODESET , "flip-vs-rmfb" }, + { 60, TEST_FLIP | TEST_DPMS | TEST_EINVAL, "flip-vs-dpms" }, + { 60, TEST_FLIP | TEST_DPMS | TEST_WITH_DUMMY_BCS, "bcs-flip-vs-dpms" }, + { 60, TEST_FLIP | TEST_DPMS | TEST_WITH_DUMMY_RCS, "rcs-flip-vs-dpms" }, + { 30, TEST_FLIP | TEST_PAN, "flip-vs-panning" }, + { 60, TEST_FLIP | TEST_PAN | TEST_WITH_DUMMY_BCS, "bcs-flip-vs-panning" }, + { 60, TEST_FLIP | TEST_PAN | TEST_WITH_DUMMY_RCS, "rcs-flip-vs-panning" }, + { 60, TEST_FLIP | TEST_MODESET | TEST_EINVAL, "flip-vs-modeset" }, + { 60, TEST_FLIP | TEST_MODESET | TEST_WITH_DUMMY_BCS, "bcs-flip-vs-modeset" }, + { 60, TEST_FLIP | TEST_MODESET | TEST_WITH_DUMMY_RCS, "rcs-flip-vs-modeset" }, + { 30, TEST_FLIP | TEST_VBLANK_EXPIRED_SEQ, + "flip-vs-expired-vblank" }, + + { 30, TEST_FLIP | TEST_VBLANK | TEST_VBLANK_ABSOLUTE | + TEST_CHECK_TS, "flip-vs-absolute-wf_vblank" }, + { 30, TEST_FLIP | TEST_VBLANK | TEST_CHECK_TS, + "flip-vs-wf_vblank" }, + { 30, TEST_FLIP | TEST_VBLANK | TEST_VBLANK_BLOCK | + TEST_CHECK_TS, "flip-vs-blocking-wf-vblank" }, + { 30, TEST_FLIP | TEST_MODESET | TEST_HANG | TEST_NOEVENT, "flip-vs-modeset-vs-hang" }, + { 30, TEST_FLIP | TEST_PAN | TEST_HANG, "flip-vs-panning-vs-hang" }, + { 30, TEST_VBLANK | TEST_HANG_ONCE, "vblank-vs-hang" }, + { 1, TEST_FLIP | TEST_EINVAL | TEST_FB_BAD_TILING, "flip-vs-bad-tiling" }, + + { 1, TEST_DPMS_OFF | TEST_MODESET | TEST_FLIP, + "flip-vs-dpms-off-vs-modeset" }, + { 1, TEST_DPMS_OFF | TEST_MODESET | TEST_FLIP | TEST_SINGLE_BUFFER, + "single-buffer-flip-vs-dpms-off-vs-modeset" }, + { 30, TEST_FLIP | TEST_NO_2X_OUTPUT | TEST_DPMS_OFF_OTHERS , "dpms-off-confusion" }, + { 0, TEST_ENOENT | TEST_NOEVENT, "nonexisting-fb" }, + { 10, TEST_DPMS_OFF | TEST_DPMS | TEST_VBLANK_RACE, "dpms-vs-vblank-race" }, + { 10, TEST_MODESET | TEST_VBLANK_RACE, "modeset-vs-vblank-race" }, + { 10, TEST_VBLANK | TEST_DPMS | TEST_RPM | TEST_TS_CONT, "vblank-vs-dpms-rpm" }, + { 10, TEST_VBLANK | TEST_MODESET | TEST_RPM | TEST_TS_CONT, "vblank-vs-modeset-rpm" }, + { 0, TEST_VBLANK | TEST_DPMS | TEST_SUSPEND | TEST_TS_CONT, "vblank-vs-dpms-suspend" }, + { 0, TEST_VBLANK | TEST_MODESET | TEST_SUSPEND | TEST_TS_CONT, "vblank-vs-modeset-suspend" }, + { 0, TEST_VBLANK | TEST_SUSPEND | TEST_TS_CONT, "vblank-vs-suspend" }, + { 0, TEST_BO_TOOBIG | TEST_NO_2X_OUTPUT, "bo-too-big" }, + }; + int i; + + igt_subtest_init(argc, argv); + igt_skip_on_simulation(); + + igt_fixture { + drm_fd = drm_open_any(); + + igt_set_vt_graphics_mode(); + igt_install_exit_handler(kms_flip_exit_handler); + get_timestamp_format(); + + bufmgr = drm_intel_bufmgr_gem_init(drm_fd, 4096); + devid = intel_get_drm_devid(drm_fd); + batch = intel_batchbuffer_alloc(bufmgr, devid); + } + + for (i = 0; i < sizeof(tests) / sizeof (tests[0]); i++) { + igt_subtest(tests[i].name) + run_test(tests[i].duration, tests[i].flags); + + if (tests[i].flags & TEST_NO_2X_OUTPUT) + continue; + + /* code doesn't disable all crtcs, so skip rpm tests */ + if (tests[i].flags & TEST_RPM) + continue; + + igt_subtest_f( "2x-%s", tests[i].name) + run_pair(tests[i].duration, tests[i].flags); + } + + igt_fork_signal_helper(); + for (i = 0; i < sizeof(tests) / sizeof (tests[0]); i++) { + /* relative blocking vblank waits that get constantly interrupt + * take forver. So don't do them. */ + if ((tests[i].flags & TEST_VBLANK_BLOCK) && + !(tests[i].flags & TEST_VBLANK_ABSOLUTE)) + continue; + + igt_subtest_f( "%s-interruptible", tests[i].name) + run_test(tests[i].duration, tests[i].flags); + + if (tests[i].flags & TEST_NO_2X_OUTPUT) + continue; + + /* code doesn't disable all crtcs, so skip rpm tests */ + if (tests[i].flags & TEST_RPM) + continue; + + igt_subtest_f( "2x-%s-interruptible", tests[i].name) + run_pair(tests[i].duration, tests[i].flags); + } + igt_stop_signal_helper(); + + /* + * Let drm_fd leak, since it's needed by the dpms restore + * exit_handler and igt_exit() won't return. + */ + + igt_exit(); +} diff --git a/tests/kms_flip_tiling.c b/tests/kms_flip_tiling.c new file mode 100644 index 00000000..ca20ad96 --- /dev/null +++ b/tests/kms_flip_tiling.c @@ -0,0 +1,145 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com> + */ + +#include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> + +#include "drmtest.h" +#include "igt_debugfs.h" +#include "igt_kms.h" +#include "ioctl_wrappers.h" + +typedef struct { + int drm_fd; + igt_display_t display; +} data_t; + +/* + * Test that a page flip from a tiled buffer to a linear one works + * correctly. First, it sets the crtc with the linear buffer and generate + * a reference crc for the pipe. Then, the crtc is set with the tiled one + * and page flip to the linear one issued. A new crc is generated and + * compared to the rerence one. + */ + +static void +fill_linear_fb(struct igt_fb *fb, data_t *data, drmModeModeInfo *mode) +{ + cairo_t *cr; + + cr = igt_get_cairo_ctx(data->drm_fd, fb); + igt_paint_test_pattern(cr, mode->hdisplay, mode->vdisplay); + cairo_destroy(cr); +} + +static void +test_flip_changes_tiling(data_t *data, igt_output_t *output) +{ + struct igt_fb linear, tiled; + drmModeModeInfo *mode; + igt_plane_t *primary; + igt_pipe_crc_t *pipe_crc; + igt_crc_t reference_crc, crc; + int fb_id, pipe, ret, width; + + pipe = 0; + pipe_crc = igt_pipe_crc_new(pipe, INTEL_PIPE_CRC_SOURCE_AUTO); + igt_output_set_pipe(output, 0); + + mode = igt_output_get_mode(output); + primary = igt_output_get_plane(output, 0); + + /* Allocate a linear buffer. Since a page flip to a buffer with + * different stride doesn't work, choose width so that the stride of + * both buffers is the same. */ + width = 512; + while (width < mode->hdisplay) + width *= 2; + fb_id = igt_create_fb(data->drm_fd, width, mode->vdisplay, + DRM_FORMAT_XRGB8888, false, &linear); + + /* fill it with a pattern that will look wrong if tiling is wrong */ + fill_linear_fb(&linear, data, mode); + + /* set the crtc and generate a reference crc */ + igt_plane_set_fb(primary, &linear); + igt_display_commit(&data->display); + igt_pipe_crc_collect_crc(pipe_crc, &reference_crc); + + /* allocate a tiled buffer and set the crtc with it */ + igt_create_color_fb(data->drm_fd, width, mode->vdisplay, + DRM_FORMAT_XRGB8888, true, 0.0, 0.0, 0.0, &tiled); + igt_plane_set_fb(primary, &tiled); + igt_display_commit(&data->display); + + /* flip to the linear buffer */ + ret = drmModePageFlip(data->drm_fd, output->config.crtc->crtc_id, + fb_id, 0, NULL); + igt_assert(ret == 0); + + igt_wait_for_vblank(data->drm_fd, pipe); + + /* get a crc and compare with the reference */ + igt_pipe_crc_collect_crc(pipe_crc, &crc); + igt_assert(igt_crc_equal(&reference_crc, &crc)); + + /* clean up */ + igt_plane_set_fb(primary, NULL); + igt_pipe_crc_free(pipe_crc); + igt_output_set_pipe(output, PIPE_ANY); + igt_display_commit(&data->display); + + igt_remove_fb(data->drm_fd, &tiled); + igt_remove_fb(data->drm_fd, &linear); +} + +static data_t data; +igt_output_t *output; + +igt_main +{ + igt_skip_on_simulation(); + + igt_fixture { + data.drm_fd = drm_open_any(); + + igt_set_vt_graphics_mode(); + + igt_require_pipe_crc(); + igt_display_init(&data.display, data.drm_fd); + } + + igt_subtest_f("flip-changes-tiling") { + for_each_connected_output(&data.display, output) + test_flip_changes_tiling(&data, output); + } + + igt_fixture { + igt_display_fini(&data.display); + } +} diff --git a/tests/kms_mmio_vs_cs_flip.c b/tests/kms_mmio_vs_cs_flip.c new file mode 100644 index 00000000..314a31d8 --- /dev/null +++ b/tests/kms_mmio_vs_cs_flip.c @@ -0,0 +1,580 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> +#include <time.h> + +#include "drmtest.h" +#include "igt_debugfs.h" +#include "igt_kms.h" +#include "intel_chipset.h" +#include "ioctl_wrappers.h" + +typedef struct { + int drm_fd; + igt_display_t display; + igt_pipe_crc_t *pipe_crc; + drm_intel_bufmgr *bufmgr; + drm_intel_bo *busy_bo; + uint32_t devid; + bool flip_done; +} data_t; + +static void exec_nop(data_t *data, uint32_t handle, unsigned int ring) +{ + struct intel_batchbuffer *batch; + drm_intel_bo *bo; + + batch = intel_batchbuffer_alloc(data->bufmgr, data->devid); + igt_assert(batch); + + bo = gem_handle_to_libdrm_bo(data->bufmgr, data->drm_fd, "", handle); + igt_assert(bo); + + /* add relocs to make sure the kernel will think we write to dst */ + BEGIN_BATCH(4); + OUT_BATCH(MI_BATCH_BUFFER_END); + OUT_BATCH(MI_NOOP); + OUT_RELOC(bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + OUT_BATCH(MI_NOOP); + ADVANCE_BATCH(); + + intel_batchbuffer_flush_on_ring(batch, ring); + intel_batchbuffer_free(batch); + + drm_intel_bo_unreference(bo); +} + +static void exec_blt(data_t *data) +{ + struct intel_batchbuffer *batch; + int w, h, pitch, i; + + batch = intel_batchbuffer_alloc(data->bufmgr, data->devid); + igt_assert(batch); + + w = 8192; + h = data->busy_bo->size / (8192 * 4); + pitch = w * 4; + + for (i = 0; i < 40; i++) { + BLIT_COPY_BATCH_START(data->devid, 0); + OUT_BATCH((3 << 24) | /* 32 bits */ + (0xcc << 16) | /* copy ROP */ + pitch); + OUT_BATCH(0 << 16 | 0); + OUT_BATCH(h << 16 | w); + OUT_RELOC(data->busy_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + BLIT_RELOC_UDW(data->devid); + OUT_BATCH(0 << 16 | 0); + OUT_BATCH(pitch); + OUT_RELOC(data->busy_bo, I915_GEM_DOMAIN_RENDER, 0, 0); + BLIT_RELOC_UDW(data->devid); + ADVANCE_BATCH(); + } + + intel_batchbuffer_flush(batch); + intel_batchbuffer_free(batch); +} + +static void page_flip_handler(int fd, unsigned int frame, unsigned int sec, + unsigned int usec, void *_data) +{ + data_t *data = _data; + + data->flip_done = true; +} + +static void wait_for_flip(data_t *data, uint32_t flip_handle) +{ + struct timeval timeout = { + .tv_sec = 3, + .tv_usec = 0, + }; + drmEventContext evctx = { + .version = DRM_EVENT_CONTEXT_VERSION, + .page_flip_handler = page_flip_handler, + }; + fd_set fds; + + FD_ZERO(&fds); + FD_SET(data->drm_fd, &fds); + + while (!data->flip_done) { + int ret = select(data->drm_fd + 1, &fds, NULL, NULL, &timeout); + + if (ret < 0 && errno == EINTR) + continue; + + igt_assert(ret >= 0); + + do_or_die(drmHandleEvent(data->drm_fd, &evctx)); + } + + /* + * The flip completion may have been signalled prematurely, so + * also submit another nop batch and wait for it to make sure + * the ring has really been drained. + */ + if (IS_GEN7(data->devid) || IS_GEN8(data->devid)) + exec_nop(data, flip_handle, I915_EXEC_BLT); + else + exec_nop(data, flip_handle, I915_EXEC_RENDER); + gem_sync(data->drm_fd, flip_handle); +} + +static void make_gpu_busy(data_t *data, uint32_t flip_handle) +{ + /* + * Make sure flip_handle has been used on the blt ring. + * This should make the flip use the same ring on gen7+. + */ + if (IS_GEN7(data->devid) || IS_GEN8(data->devid)) + exec_nop(data, flip_handle, I915_EXEC_BLT); + + /* + * Add a pile commands to the ring. The flip will be + * stuck behing these commands and hence gets delayed + * significantly. + */ + exec_blt(data); + + /* + * Make sure the render ring will block until the blt ring is clear. + * This is in case the flip will execute on the render ring and the + * blits were on the blt ring (this will be the case on gen6 at least). + * + * We can't add an explicit dependency between flip_handle and the + * blits since that would cause the driver to block until the blits + * have completed before it will perform a subsequent mmio flip, + * and so the test would fail to exercise the mmio vs. CS flip race. + */ + if (HAS_BLT_RING(data->devid)) + exec_nop(data, data->busy_bo->handle, I915_EXEC_RENDER); +} + +/* + * 1. set primary plane to full red + * 2. grab a reference crc + * 3. set primary plane to full blue + * 4. queue lots of GPU activity to delay the subsequent page flip + * 5. queue a page flip to the same blue fb + * 6. toggle a fullscreen sprite (green) on and back off again + * 7. set primary plane to red fb + * 8. wait for GPU to finish + * 9. compare current crc with reference crc + * + * We expect the primary plane to display full red at the end. + * If the sprite operations have interfered with the page flip, + * the driver may have mistakenly completed the flip before + * it was executed by the CS, and hence the subsequent mmio + * flips may have overtaken it. So once we've finished everything + * the CS flip may have been the last thing to occur, which means + * the primary plane may be full blue instead of the red it's + * supposed to be. + */ +static bool +test_plane(data_t *data, igt_output_t *output, enum pipe pipe, enum igt_plane plane) +{ + struct igt_fb red_fb, green_fb, blue_fb; + drmModeModeInfo *mode; + igt_plane_t *primary, *sprite; + igt_crc_t ref_crc, crc; + int ret; + + igt_output_set_pipe(output, pipe); + igt_display_commit(&data->display); + + if (!output->valid) { + igt_output_set_pipe(output, PIPE_ANY); + igt_display_commit(&data->display); + return false; + } + + primary = igt_output_get_plane(output, 0); + sprite = igt_output_get_plane(output, plane); + + mode = igt_output_get_mode(output); + igt_create_color_fb(data->drm_fd, mode->hdisplay, mode->vdisplay, + DRM_FORMAT_XRGB8888, + false, /* tiled */ + 1.0, 0.0, 0.0, + &red_fb); + igt_create_color_fb(data->drm_fd, mode->hdisplay, mode->vdisplay, + DRM_FORMAT_XRGB8888, + false, /* tiled */ + 0.0, 1.0, 0.0, + &green_fb); + igt_create_color_fb(data->drm_fd, mode->hdisplay, mode->vdisplay, + DRM_FORMAT_XRGB8888, + false, /* tiled */ + 0.0, 0.0, 1.0, + &blue_fb); + + /* + * Make sure these buffers are suited for display use + * because most of the modeset operations must be fast + * later on. + */ + igt_plane_set_fb(primary, &blue_fb); + igt_display_commit(&data->display); + igt_plane_set_fb(sprite, &green_fb); + igt_display_commit(&data->display); + igt_plane_set_fb(sprite, NULL); + igt_display_commit(&data->display); + + if (data->pipe_crc) + igt_pipe_crc_free(data->pipe_crc); + data->pipe_crc = igt_pipe_crc_new(pipe, INTEL_PIPE_CRC_SOURCE_AUTO); + if (!data->pipe_crc) { + igt_info("auto crc not supported on this connector with crtc %i\n", + pipe); + + igt_plane_set_fb(primary, NULL); + igt_plane_set_fb(sprite, NULL); + igt_output_set_pipe(output, PIPE_ANY); + igt_display_commit(&data->display); + + igt_remove_fb(data->drm_fd, &red_fb); + igt_remove_fb(data->drm_fd, &green_fb); + igt_remove_fb(data->drm_fd, &blue_fb); + + return false; + } + + /* set red fb and grab reference crc */ + igt_plane_set_fb(primary, &red_fb); + igt_display_commit(&data->display); + igt_pipe_crc_collect_crc(data->pipe_crc, &ref_crc); + + ret = drmModeSetCrtc(data->drm_fd, output->config.crtc->crtc_id, + blue_fb.fb_id, 0, 0, &output->id, 1, + mode); + igt_assert(ret == 0); + + make_gpu_busy(data, blue_fb.gem_handle); + + data->flip_done = false; + ret = drmModePageFlip(data->drm_fd, output->config.crtc->crtc_id, + blue_fb.fb_id, DRM_MODE_PAGE_FLIP_EVENT, data); + igt_assert(ret == 0); + + /* + * Toggle a fullscreen sprite on and back off. This will result + * in the primary plane getting disabled and re-enbled, and that + * leads to mmio flips. The driver may then mistake the flip done + * interrupts from the mmio flips as the flip done interrupts for + * the CS flip, and hence subsequent mmio flips won't wait for the + * CS flips like they should. + */ + ret = drmModeSetPlane(data->drm_fd, + sprite->drm_plane->plane_id, + output->config.crtc->crtc_id, + green_fb.fb_id, 0, + 0, 0, mode->hdisplay, mode->vdisplay, + 0, 0, mode->hdisplay << 16, mode->vdisplay << 16); + igt_assert(ret == 0); + ret = drmModeSetPlane(data->drm_fd, + sprite->drm_plane->plane_id, + output->config.crtc->crtc_id, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0); + igt_assert(ret == 0); + + /* + * Set primary plane to red fb. This should wait for the CS flip + * to complete. But if the kernel mistook the flip done interrupt + * from the mmio flip as the flip done from the CS flip, this will + * not wait for anything. And hence the the CS flip will actually + * occur after this mmio flip. + */ + ret = drmModeSetCrtc(data->drm_fd, output->config.crtc->crtc_id, + red_fb.fb_id, 0, 0, &output->id, 1, + mode); + igt_assert(ret == 0); + + /* Make sure the flip has been executed */ + wait_for_flip(data, blue_fb.gem_handle); + + /* Grab crc and compare with the extected result */ + igt_pipe_crc_collect_crc(data->pipe_crc, &crc); + + igt_plane_set_fb(primary, NULL); + igt_display_commit(&data->display); + + igt_remove_fb(data->drm_fd, &red_fb); + igt_remove_fb(data->drm_fd, &green_fb); + igt_remove_fb(data->drm_fd, &blue_fb); + + igt_pipe_crc_free(data->pipe_crc); + data->pipe_crc = NULL; + + igt_output_set_pipe(output, PIPE_ANY); + igt_display_commit(&data->display); + + igt_assert(igt_crc_equal(&ref_crc, &crc)); + + return true; +} + +/* + * 1. set primary plane to full red + * 2. grab a reference crc + * 3. set primary plane to full green + * 4. wait for vblank + * 5. pan primary plane a bit (to cause a mmio flip w/o vblank wait) + * 6. queue lots of GPU activity to delay the subsequent page flip + * 6. queue a page flip to a blue fb + * 7. set primary plane to red fb + * 8. wait for GPU to finish + * 9. compare current crc with reference crc + * + * We expect the primary plane to display full red at the end. + * If the previously schedule primary plane pan operation has interfered + * with the following page flip, the driver may have mistakenly completed + * the flip before it was executed by the CS, and hence the subsequent mmio + * flips may have overtaken it. So once we've finished everything + * the CS flip may have been the last thing to occur, which means + * the primary plane may be full blue instead of the red it's + * supposed to be. + */ +static bool +test_crtc(data_t *data, igt_output_t *output, enum pipe pipe) +{ + struct igt_fb red_fb, green_fb, blue_fb; + drmModeModeInfo *mode; + igt_plane_t *primary; + igt_crc_t ref_crc, crc; + int ret; + + igt_output_set_pipe(output, pipe); + igt_display_commit(&data->display); + + if (!output->valid) { + igt_output_set_pipe(output, PIPE_ANY); + igt_display_commit(&data->display); + return false; + } + + primary = igt_output_get_plane(output, 0); + + mode = igt_output_get_mode(output); + igt_create_color_fb(data->drm_fd, mode->hdisplay, mode->vdisplay+1, + DRM_FORMAT_XRGB8888, + false, /* tiled */ + 1.0, 0.0, 0.0, + &red_fb); + igt_create_color_fb(data->drm_fd, mode->hdisplay, mode->vdisplay+1, + DRM_FORMAT_XRGB8888, + false, /* tiled */ + 0.0, 0.0, 1.0, + &blue_fb); + igt_create_color_fb(data->drm_fd, mode->hdisplay, mode->vdisplay+1, + DRM_FORMAT_XRGB8888, + false, /* tiled */ + 0.0, 1.0, 0.0, + &green_fb); + + /* + * Make sure these buffers are suited for display use + * because most of the modeset operations must be fast + * later on. + */ + igt_plane_set_fb(primary, &green_fb); + igt_display_commit(&data->display); + igt_plane_set_fb(primary, &blue_fb); + igt_display_commit(&data->display); + + if (data->pipe_crc) + igt_pipe_crc_free(data->pipe_crc); + data->pipe_crc = igt_pipe_crc_new(pipe, INTEL_PIPE_CRC_SOURCE_AUTO); + if (!data->pipe_crc) { + igt_info("auto crc not supported on this connector with crtc %i\n", + pipe); + + igt_plane_set_fb(primary, NULL); + igt_output_set_pipe(output, PIPE_ANY); + igt_display_commit(&data->display); + + igt_remove_fb(data->drm_fd, &red_fb); + igt_remove_fb(data->drm_fd, &green_fb); + igt_remove_fb(data->drm_fd, &blue_fb); + + return false; + } + + /* set red fb and grab reference crc */ + igt_plane_set_fb(primary, &red_fb); + igt_display_commit(&data->display); + igt_pipe_crc_collect_crc(data->pipe_crc, &ref_crc); + + /* + * Further down we need to issue an mmio flip w/o the kernel + * waiting for vblank. The easiest way is to just pan within + * the same FB. So pan away a bit here, and later we undo this + * with another pan which will result in the desired mmio flip. + */ + ret = drmModeSetCrtc(data->drm_fd, output->config.crtc->crtc_id, + green_fb.fb_id, 0, 1, &output->id, 1, + mode); + igt_assert(ret == 0); + + /* + * Make it more likely that the CS flip has been submitted into the + * ring by the time the mmio flip from the drmModeSetCrtc() below + * completes. The driver will then mistake the flip done interrupt + * from the mmio flip as the flip done interrupt from the CS flip. + */ + igt_wait_for_vblank(data->drm_fd, pipe); + + /* now issue the mmio flip w/o vblank waits in the kernel, ie. pan a bit */ + ret = drmModeSetCrtc(data->drm_fd, output->config.crtc->crtc_id, + green_fb.fb_id, 0, 0, &output->id, 1, + mode); + igt_assert(ret == 0); + + make_gpu_busy(data, blue_fb.gem_handle); + + /* + * Submit the CS flip. The commands must be emitted into the ring + * before the mmio flip from the panning operation completes. + */ + data->flip_done = false; + ret = drmModePageFlip(data->drm_fd, output->config.crtc->crtc_id, + blue_fb.fb_id, DRM_MODE_PAGE_FLIP_EVENT, data); + igt_assert(ret == 0); + + /* + * Set primary plane to red fb. This should wait for the CS flip + * to complete. But if the kernel mistook the flip done interrupt + * from the mmio flip as the flip done from the CS flip, this will + * not wait for anything. And hence the the CS flip will actually + * occur after this mmio flip. + */ + ret = drmModeSetCrtc(data->drm_fd, output->config.crtc->crtc_id, + red_fb.fb_id, 0, 0, &output->id, 1, + mode); + igt_assert(ret == 0); + + /* Make sure the flip has been executed */ + wait_for_flip(data, blue_fb.gem_handle); + + /* Grab crc and compare with the extected result */ + igt_pipe_crc_collect_crc(data->pipe_crc, &crc); + + igt_plane_set_fb(primary, NULL); + igt_display_commit(&data->display); + + igt_remove_fb(data->drm_fd, &red_fb); + igt_remove_fb(data->drm_fd, &green_fb); + igt_remove_fb(data->drm_fd, &blue_fb); + + igt_pipe_crc_free(data->pipe_crc); + data->pipe_crc = NULL; + + igt_output_set_pipe(output, PIPE_ANY); + igt_display_commit(&data->display); + + igt_assert(igt_crc_equal(&ref_crc, &crc)); + + return true; +} + +static void +run_plane_test_for_pipe(data_t *data, enum pipe pipe) +{ + igt_output_t *output; + enum igt_plane plane = 1; /* testing with one sprite is enough */ + int valid_tests = 0; + + igt_require(data->display.pipes[pipe].n_planes > 2); + + for_each_connected_output(&data->display, output) { + if (test_plane(data, output, pipe, plane)) + valid_tests++; + } + + igt_require_f(valid_tests, "no valid crtc/connector combinations found\n"); +} + +static void +run_crtc_test_for_pipe(data_t *data, enum pipe pipe) +{ + igt_output_t *output; + int valid_tests = 0; + + for_each_connected_output(&data->display, output) { + if (test_crtc(data, output, pipe)) + valid_tests++; + } + + igt_require_f(valid_tests, "no valid crtc/connector combinations found\n"); +} + +static data_t data; + +igt_main +{ + int pipe; + + igt_skip_on_simulation(); + + igt_fixture { + data.drm_fd = drm_open_any(); + + igt_set_vt_graphics_mode(); + + data.devid = intel_get_drm_devid(data.drm_fd); + + igt_require_pipe_crc(); + igt_display_init(&data.display, data.drm_fd); + + data.bufmgr = drm_intel_bufmgr_gem_init(data.drm_fd, 4096); + igt_assert(data.bufmgr); + drm_intel_bufmgr_gem_enable_reuse(data.bufmgr); + + data.busy_bo = drm_intel_bo_alloc(data.bufmgr, "bo", + 64*1024*1024, 4096); + gem_set_tiling(data.drm_fd, data.busy_bo->handle, 0, 4096); + } + + igt_subtest_f("setplane_vs_cs_flip") { + for (pipe = 0; pipe < data.display.n_pipes; pipe++) + run_plane_test_for_pipe(&data, pipe); + } + + igt_subtest_f("setcrtc_vs_cs_flip") { + for (pipe = 0; pipe < data.display.n_pipes; pipe++) + run_crtc_test_for_pipe(&data, pipe); + } + + igt_fixture { + drm_intel_bo_unreference(data.busy_bo); + drm_intel_bufmgr_destroy(data.bufmgr); + igt_display_fini(&data.display); + } +} diff --git a/tests/kms_pipe_crc_basic.c b/tests/kms_pipe_crc_basic.c new file mode 100644 index 00000000..9eec4e6f --- /dev/null +++ b/tests/kms_pipe_crc_basic.c @@ -0,0 +1,231 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> + +#include "drmtest.h" +#include "igt_debugfs.h" +#include "igt_kms.h" +#include "igt_aux.h" +#include "ioctl_wrappers.h" + +typedef struct { + int drm_fd; + igt_display_t display; + struct igt_fb fb; +} data_t; + +static uint64_t submit_batch(int fd, unsigned ring_id) +{ + const uint32_t batch[] = { MI_NOOP, + MI_BATCH_BUFFER_END }; + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 exec; + uint64_t presumed_offset; + + gem_require_ring(fd, ring_id); + + exec.handle = gem_create(fd, 4096); + gem_write(fd, exec.handle, 0, batch, sizeof(batch)); + exec.relocation_count = 0; + exec.relocs_ptr = 0; + exec.alignment = 0; + exec.offset = 0; + exec.flags = 0; + exec.rsvd1 = 0; + exec.rsvd2 = 0; + + execbuf.buffers_ptr = (uintptr_t)&exec; + execbuf.buffer_count = 1; + execbuf.batch_start_offset = 0; + execbuf.batch_len = sizeof(batch); + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = ring_id; + i915_execbuffer2_set_context_id(execbuf, 0); + execbuf.rsvd2 = 0; + + gem_execbuf(fd, &execbuf); + gem_sync(fd, exec.handle); + presumed_offset = exec.offset; + + igt_set_stop_rings(igt_to_stop_ring_flag(ring_id)); + + gem_execbuf(fd, &execbuf); + gem_sync(fd, exec.handle); + + igt_assert(igt_get_stop_rings() == STOP_RING_NONE); + igt_assert(presumed_offset == exec.offset); + + gem_close(fd, exec.handle); + + return exec.offset; +} + +static void test_bad_command(data_t *data, const char *cmd) +{ + FILE *ctl; + size_t written; + + ctl = igt_debugfs_fopen("i915_display_crc_ctl", "r+"); + written = fwrite(cmd, 1, strlen(cmd), ctl); + fflush(ctl); + igt_assert_cmpint(written, ==, (strlen(cmd))); + igt_assert(ferror(ctl)); + igt_assert_cmpint(errno, ==, EINVAL); + + fclose(ctl); +} + +#define TEST_SEQUENCE (1<<0) + +static void test_read_crc(data_t *data, int pipe, unsigned flags) +{ + igt_display_t *display = &data->display; + igt_pipe_crc_t *pipe_crc; + igt_crc_t *crcs = NULL; + int valid_connectors = 0; + igt_output_t *output; + + igt_skip_on(pipe >= data->display.n_pipes); + + for_each_connected_output(display, output) { + igt_plane_t *primary; + drmModeModeInfo *mode; + + igt_output_set_pipe(output, pipe); + + igt_info("%s: Testing connector %s using pipe %c\n", + igt_subtest_name(), igt_output_name(output), + pipe_name(pipe)); + + mode = igt_output_get_mode(output); + igt_create_color_fb(data->drm_fd, + mode->hdisplay, mode->vdisplay, + DRM_FORMAT_XRGB8888, + false, /* tiled */ + 0.0, 1.0, 0.0, + &data->fb); + + primary = igt_output_get_plane(output, 0); + igt_plane_set_fb(primary, &data->fb); + + igt_display_commit(display); + + pipe_crc = igt_pipe_crc_new(pipe, INTEL_PIPE_CRC_SOURCE_AUTO); + + if (!pipe_crc) + continue; + valid_connectors++; + + igt_pipe_crc_start(pipe_crc); + + /* wait for 3 vblanks and the corresponding 3 CRCs */ + igt_pipe_crc_get_crcs(pipe_crc, 3, &crcs); + + igt_pipe_crc_stop(pipe_crc); + + /* ensure the CRCs are not all 0s */ + igt_assert(!igt_crc_is_null(&crcs[0])); + igt_assert(!igt_crc_is_null(&crcs[1])); + igt_assert(!igt_crc_is_null(&crcs[2])); + + /* and ensure that they'are all equal, we haven't changed the fb */ + igt_assert(igt_crc_equal(&crcs[0], &crcs[1])); + igt_assert(igt_crc_equal(&crcs[1], &crcs[2])); + + if (flags & TEST_SEQUENCE) { + igt_assert(crcs[0].frame + 1 == crcs[1].frame); + igt_assert(crcs[1].frame + 1 == crcs[2].frame); + } + + free(crcs); + igt_pipe_crc_free(pipe_crc); + igt_remove_fb(data->drm_fd, &data->fb); + igt_plane_set_fb(primary, NULL); + + igt_output_set_pipe(output, PIPE_ANY); + } + + igt_require_f(valid_connectors, "No connector found for pipe %i\n", pipe); + +} + +data_t data = {0, }; + +igt_main +{ + igt_skip_on_simulation(); + + igt_fixture { + data.drm_fd = drm_open_any(); + + igt_set_vt_graphics_mode(); + + igt_require_pipe_crc(); + + igt_display_init(&data.display, data.drm_fd); + } + + igt_subtest("bad-pipe") + test_bad_command(&data, "pipe D none"); + + igt_subtest("bad-source") + test_bad_command(&data, "pipe A foo"); + + igt_subtest("bad-nb-words-1") + test_bad_command(&data, "pipe foo"); + + igt_subtest("bad-nb-words-3") + test_bad_command(&data, "pipe A none option"); + + for (int i = 0; i < 3; i++) { + igt_subtest_f("read-crc-pipe-%c", 'A'+i) + test_read_crc(&data, i, 0); + + igt_subtest_f("read-crc-pipe-%c-frame-sequence", 'A'+i) + test_read_crc(&data, i, TEST_SEQUENCE); + + igt_subtest_f("suspend-read-crc-pipe-%c", 'A'+i) { + igt_system_suspend_autoresume(); + + test_read_crc(&data, i, 0); + } + + igt_subtest_f("hang-read-crc-pipe-%c", 'A'+i) { + submit_batch(data.drm_fd, I915_EXEC_RENDER); + + test_read_crc(&data, i, 0); + } + } + + igt_fixture { + igt_display_fini(&data.display); + } +} diff --git a/tests/kms_plane.c b/tests/kms_plane.c new file mode 100644 index 00000000..5db09473 --- /dev/null +++ b/tests/kms_plane.c @@ -0,0 +1,242 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Damien Lespiau <damien.lespiau@intel.com> + */ + +#include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> + +#include "drmtest.h" +#include "igt_debugfs.h" +#include "igt_kms.h" + +typedef struct { + int drm_fd; + igt_display_t display; +} data_t; + +/* + * Plane position test. + * - We start by grabbing a reference CRC of a full green fb being scanned + * out on the primary plane + * - Then we scannout 2 planes: + * - the primary plane uses a green fb with a black rectangle + * - a plane, on top of the primary plane, with a green fb that is set-up + * to cover the black rectangle of the primary plane fb + * The resulting CRC should be identical to the reference CRC + */ + +typedef struct { + data_t *data; + igt_pipe_crc_t *pipe_crc; + igt_crc_t reference_crc; +} test_position_t; + +/* + * create a green fb with a black rectangle at (rect_x,rect_y) and of size + * (rect_w,rect_h) + */ +static void +create_fb_for_mode__position(data_t *data, drmModeModeInfo *mode, + double rect_x, double rect_y, + double rect_w, double rect_h, + struct igt_fb *fb /* out */) +{ + unsigned int fb_id; + cairo_t *cr; + + fb_id = igt_create_fb(data->drm_fd, + mode->hdisplay, mode->vdisplay, + DRM_FORMAT_XRGB8888, + false /* tiling */, + fb); + igt_assert(fb_id); + + cr = igt_get_cairo_ctx(data->drm_fd, fb); + igt_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay, + 0.0, 1.0, 0.0); + igt_paint_color(cr, rect_x, rect_y, rect_w, rect_h, 0.0, 0.0, 0.0); + igt_assert(cairo_status(cr) == 0); + cairo_destroy(cr); +} + +static void +test_position_init(test_position_t *test, igt_output_t *output, enum pipe pipe) +{ + data_t *data = test->data; + struct igt_fb green_fb; + drmModeModeInfo *mode; + igt_plane_t *primary; + + test->pipe_crc = igt_pipe_crc_new(pipe, INTEL_PIPE_CRC_SOURCE_AUTO); + + igt_output_set_pipe(output, pipe); + primary = igt_output_get_plane(output, 0); + + mode = igt_output_get_mode(output); + igt_create_color_fb(data->drm_fd, mode->hdisplay, mode->vdisplay, + DRM_FORMAT_XRGB8888, + false, /* tiled */ + 0.0, 1.0, 0.0, + &green_fb); + igt_plane_set_fb(primary, &green_fb); + + igt_display_commit(&data->display); + + igt_pipe_crc_collect_crc(test->pipe_crc, &test->reference_crc); + + igt_plane_set_fb(primary, NULL); + igt_display_commit(&data->display); + + igt_remove_fb(data->drm_fd, &green_fb); +} + +static void +test_position_fini(test_position_t *test, igt_output_t *output) +{ + igt_pipe_crc_free(test->pipe_crc); + + igt_output_set_pipe(output, PIPE_ANY); + igt_display_commit(&test->data->display); +} + +enum { + TEST_POSITION_FULLY_COVERED = 1 << 0, +}; + +static void +test_plane_position_with_output(data_t *data, + enum pipe pipe, + enum igt_plane plane, + igt_output_t *output, + unsigned int flags) +{ + test_position_t test = { .data = data }; + igt_plane_t *primary, *sprite; + struct igt_fb primary_fb, sprite_fb; + drmModeModeInfo *mode; + igt_crc_t crc; + + igt_info("Testing connector %s using pipe %c plane %d\n", + igt_output_name(output), pipe_name(pipe), plane); + + test_position_init(&test, output, pipe); + + mode = igt_output_get_mode(output); + primary = igt_output_get_plane(output, 0); + sprite = igt_output_get_plane(output, plane); + + create_fb_for_mode__position(data, mode, 100, 100, 64, 64, + &primary_fb); + igt_plane_set_fb(primary, &primary_fb); + + igt_create_color_fb(data->drm_fd, + 64, 64, /* width, height */ + DRM_FORMAT_XRGB8888, + false, /* tiled */ + 0.0, 1.0, 0.0, + &sprite_fb); + igt_plane_set_fb(sprite, &sprite_fb); + + if (flags & TEST_POSITION_FULLY_COVERED) + igt_plane_set_position(sprite, 100, 100); + else + igt_plane_set_position(sprite, 132, 132); + + igt_display_commit(&data->display); + + igt_pipe_crc_collect_crc(test.pipe_crc, &crc); + + if (flags & TEST_POSITION_FULLY_COVERED) + igt_assert(igt_crc_equal(&test.reference_crc, &crc)); + else + igt_assert(!igt_crc_equal(&test.reference_crc, &crc)); + + igt_plane_set_fb(primary, NULL); + igt_plane_set_fb(sprite, NULL); + + test_position_fini(&test, output); +} + +static void +test_plane_position(data_t *data, enum pipe pipe, enum igt_plane plane, + unsigned int flags) +{ + igt_output_t *output; + + igt_skip_on(pipe >= data->display.n_pipes); + igt_skip_on(plane >= data->display.pipes[pipe].n_planes); + + for_each_connected_output(&data->display, output) + test_plane_position_with_output(data, pipe, plane, output, + flags); +} + +static void +run_tests_for_pipe_plane(data_t *data, enum pipe pipe, enum igt_plane plane) +{ + igt_subtest_f("plane-position-covered-pipe-%c-plane-%d", + pipe_name(pipe), plane) + test_plane_position(data, pipe, plane, + TEST_POSITION_FULLY_COVERED); + + igt_subtest_f("plane-position-hole-pipe-%c-plane-%d", + pipe_name(pipe), plane) + test_plane_position(data, pipe, plane, 0); +} + +static void +run_tests_for_pipe(data_t *data, enum pipe pipe) +{ + int plane; + + for (plane = 1; plane < IGT_MAX_PLANES; plane++) + run_tests_for_pipe_plane(data, pipe, plane); +} + +static data_t data; + +igt_main +{ + + igt_skip_on_simulation(); + + igt_fixture { + data.drm_fd = drm_open_any(); + + igt_set_vt_graphics_mode(); + + igt_require_pipe_crc(); + igt_display_init(&data.display, data.drm_fd); + } + + for (int pipe = 0; pipe < 3; pipe++) + run_tests_for_pipe(&data, pipe); + + igt_fixture { + igt_display_fini(&data.display); + } +} diff --git a/tests/kms_render.c b/tests/kms_render.c new file mode 100644 index 00000000..6c742e23 --- /dev/null +++ b/tests/kms_render.c @@ -0,0 +1,249 @@ +/* + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Imre Deak <imre.deak@intel.com> + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <cairo.h> +#include <errno.h> +#include <stdint.h> +#include <unistd.h> +#include <sys/time.h> + +#include "drmtest.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_io.h" +#include "intel_chipset.h" +#include "igt_kms.h" +#include "ioctl_wrappers.h" + +drmModeRes *resources; +int drm_fd; +static drm_intel_bufmgr *bufmgr; +struct intel_batchbuffer *batch; +uint32_t devid; + +enum test_flags { + TEST_DIRECT_RENDER = 0x01, + TEST_GPU_BLIT = 0x02, +}; + +static int paint_fb(struct igt_fb *fb, const char *test_name, + const char *mode_format_str, const char *cconf_str) +{ + cairo_t *cr; + + cr = igt_get_cairo_ctx(drm_fd, fb); + + igt_paint_color_gradient(cr, 0, 0, fb->width, fb->height, 1, 1, 1); + igt_paint_test_pattern(cr, fb->width, fb->height); + + cairo_move_to(cr, fb->width / 2, fb->height / 2); + cairo_set_font_size(cr, 36); + igt_cairo_printf_line(cr, align_hcenter, 10, "%s", test_name); + igt_cairo_printf_line(cr, align_hcenter, 10, "%s", mode_format_str); + igt_cairo_printf_line(cr, align_hcenter, 10, "%s", cconf_str); + + cairo_destroy(cr); + + return 0; +} + +static void gpu_blit(struct igt_fb *dst_fb, struct igt_fb *src_fb) +{ + drm_intel_bo *dst_bo; + drm_intel_bo *src_bo; + int bpp; + + igt_assert(dst_fb->drm_format == src_fb->drm_format); + igt_assert(src_fb->drm_format == DRM_FORMAT_RGB565 || + igt_drm_format_to_bpp(src_fb->drm_format) != 16); + bpp = igt_drm_format_to_bpp(src_fb->drm_format); + dst_bo = gem_handle_to_libdrm_bo(bufmgr, drm_fd, "destination", + dst_fb->gem_handle); + igt_assert(dst_bo); + src_bo = gem_handle_to_libdrm_bo(bufmgr, drm_fd, "source", + src_fb->gem_handle); + igt_assert(src_bo); + + intel_blt_copy(batch, + src_bo, 0, 0, src_fb->width * bpp / 8, + dst_bo, 0, 0, dst_fb->width * bpp / 8, + src_fb->width, src_fb->height, bpp); + intel_batchbuffer_flush(batch); + gem_quiescent_gpu(drm_fd); + + drm_intel_bo_unreference(src_bo); + drm_intel_bo_unreference(dst_bo); +} + +static int test_format(const char *test_name, + struct kmstest_connector_config *cconf, + drmModeModeInfo *mode, uint32_t format, + enum test_flags flags) +{ + int width; + int height; + struct igt_fb fb[2]; + char *mode_format_str; + char *cconf_str; + int ret; + + ret = asprintf(&mode_format_str, "%s @ %dHz / %s", + mode->name, mode->vrefresh, igt_format_str(format)); + igt_assert(ret > 0); + ret = asprintf(&cconf_str, "pipe %s, encoder %s, connector %s", + kmstest_pipe_str(cconf->pipe), + kmstest_encoder_type_str(cconf->encoder->encoder_type), + kmstest_connector_type_str(cconf->connector->connector_type)); + igt_assert(ret > 0); + + igt_info("Beginning test %s with %s on %s\n", + test_name, mode_format_str, cconf_str); + + width = mode->hdisplay; + height = mode->vdisplay; + + if (!igt_create_fb(drm_fd, width, height, format, false, &fb[0])) + goto err1; + + if (!igt_create_fb(drm_fd, width, height, format, false, &fb[1])) + goto err2; + + if (drmModeSetCrtc(drm_fd, cconf->crtc->crtc_id, fb[0].fb_id, + 0, 0, &cconf->connector->connector_id, 1, + mode)) + goto err2; + do_or_die(drmModePageFlip(drm_fd, cconf->crtc->crtc_id, fb[0].fb_id, + 0, NULL)); + sleep(2); + + if (flags & TEST_DIRECT_RENDER) { + paint_fb(&fb[0], test_name, mode_format_str, cconf_str); + } else if (flags & TEST_GPU_BLIT) { + paint_fb(&fb[1], test_name, mode_format_str, cconf_str); + gpu_blit(&fb[0], &fb[1]); + } + sleep(5); + + igt_info("Test %s with %s on %s: PASSED\n", + test_name, mode_format_str, cconf_str); + free(mode_format_str); + free(cconf_str); + + igt_remove_fb(drm_fd, &fb[1]); + igt_remove_fb(drm_fd, &fb[0]); + + return 0; + +err2: + igt_remove_fb(drm_fd, &fb[0]); +err1: + igt_info("Test %s with %s on %s: SKIPPED\n", + test_name, mode_format_str, cconf_str); + free(mode_format_str); + free(cconf_str); + + return -1; +} + +static void test_connector(const char *test_name, + struct kmstest_connector_config *cconf, + enum test_flags flags) +{ + const uint32_t *formats; + int format_count; + int i; + + igt_get_all_formats(&formats, &format_count); + for (i = 0; i < format_count; i++) + test_format(test_name, + cconf, &cconf->connector->modes[i], + formats[i], flags); +} + +static int run_test(const char *test_name, enum test_flags flags) +{ + int i; + + resources = drmModeGetResources(drm_fd); + igt_assert(resources); + + /* Find any connected displays */ + for (i = 0; i < resources->count_connectors; i++) { + uint32_t connector_id; + int j; + + connector_id = resources->connectors[i]; + for (j = 0; j < resources->count_crtcs; j++) { + struct kmstest_connector_config cconf; + int ret; + + ret = kmstest_get_connector_config(drm_fd, connector_id, + 1 << j, &cconf); + if (ret < 0) + continue; + + test_connector(test_name, &cconf, flags); + + kmstest_free_connector_config(&cconf); + } + } + + drmModeFreeResources(resources); + + return 1; +} + +igt_main +{ + struct { + enum test_flags flags; + const char *name; + } tests[] = { + { TEST_DIRECT_RENDER, "direct-render" }, + { TEST_GPU_BLIT, "gpu-blit" }, + }; + int i; + + igt_skip_on_simulation(); + + igt_fixture { + drm_fd = drm_open_any(); + + bufmgr = drm_intel_bufmgr_gem_init(drm_fd, 4096); + devid = intel_get_drm_devid(drm_fd); + batch = intel_batchbuffer_alloc(bufmgr, devid); + + igt_set_vt_graphics_mode(); + } + + for (i = 0; i < ARRAY_SIZE(tests); i++) { + igt_subtest(tests[i].name) + run_test(tests[i].name, tests[i].flags); + } + + igt_fixture + close(drm_fd); +} diff --git a/tests/kms_setmode.c b/tests/kms_setmode.c new file mode 100644 index 00000000..0b765a9c --- /dev/null +++ b/tests/kms_setmode.c @@ -0,0 +1,742 @@ +/* + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Imre Deak <imre.deak@intel.com> + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <cairo.h> +#include <errno.h> +#include <stdint.h> +#include <unistd.h> +#include <string.h> +#include <getopt.h> +#include <sys/time.h> + +#include "drmtest.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_io.h" +#include "igt_kms.h" + +#define MAX_CONNECTORS 10 +#define MAX_CRTCS 3 + +/* max combinations with repetitions */ +#define MAX_COMBINATION_COUNT \ + (MAX_CONNECTORS * MAX_CONNECTORS * MAX_CONNECTORS) +#define MAX_COMBINATION_ELEMS MAX_CRTCS + +static int drm_fd; +static drmModeRes *drm_resources; +static int filter_test_id; +static bool dry_run; + +const drmModeModeInfo mode_640_480 = { + .name = "640x480", + .vrefresh = 60, + .clock = 25200, + + .hdisplay = 640, + .hsync_start = 656, + .hsync_end = 752, + .htotal = 800, + + .vdisplay = 480, + .vsync_start = 490, + .vsync_end = 492, + .vtotal = 525, + + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, +}; + +enum test_flags { + TEST_INVALID = 0x01, + TEST_CLONE = 0x02, + TEST_SINGLE_CRTC_CLONE = 0x04, + TEST_EXCLUSIVE_CRTC_CLONE = 0x08, +}; + +struct test_config { + const char *name; + enum test_flags flags; + drmModeRes *resources; +}; + +struct connector_config { + drmModeConnector *connector; + int crtc_idx; + bool connected; + drmModeModeInfo default_mode; +}; + +struct crtc_config { + int crtc_idx; + int crtc_id; + int pipe_id; + int connector_count; + struct connector_config *cconfs; + struct igt_fb fb_info; + drmModeModeInfo mode; +}; + +static bool drm_mode_equal(drmModeModeInfo *m1, drmModeModeInfo *m2) +{ +#define COMP(x) do { if (m1->x != m2->x) return false; } while (0) + COMP(vrefresh); + COMP(clock); + COMP(hdisplay); + COMP(hsync_start); + COMP(hsync_end); + COMP(htotal); + COMP(vdisplay); + COMP(vsync_start); + COMP(vsync_end); + COMP(vtotal); + COMP(flags); + + return true; +} + +static bool connector_supports_mode(drmModeConnector *connector, + drmModeModeInfo *mode) +{ + int i; + + for (i = 0; i < connector->count_modes; i++) + if (drm_mode_equal(&connector->modes[i], mode)) + return true; + + return false; +} + +static bool crtc_supports_mode(struct crtc_config *crtc, drmModeModeInfo *mode) +{ + int i; + + for (i = 0; i < crtc->connector_count; i++) { + if (!connector_supports_mode(crtc->cconfs[i].connector, mode)) + return false; + } + + return true; +} + +static int paint_fb(struct igt_fb *fb, const char *test_name, + const char **crtc_str, int crtc_count, int current_crtc_idx) +{ + double x, y; + cairo_t *cr; + int i; + + cr = igt_get_cairo_ctx(drm_fd, fb); + + igt_paint_test_pattern(cr, fb->width, fb->height); + + cairo_move_to(cr, fb->width / 2, fb->height / 2); + cairo_set_font_size(cr, 24); + igt_cairo_printf_line(cr, align_hcenter, 40, "%s", test_name); + + cairo_get_current_point(cr, &x, &y); + cairo_move_to(cr, 60, y); + + for (i = 0; i < crtc_count; i++) { + if (i == current_crtc_idx) { + cairo_get_current_point(cr, &x, &y); + cairo_move_to(cr, x - 20, y); + igt_cairo_printf_line(cr, align_right, 20, "X"); + cairo_move_to(cr, x, y); + } + igt_cairo_printf_line(cr, align_left, 20, "%s", + crtc_str[i]); + } + + cairo_destroy(cr); + + return 0; +} + +static void create_fb_for_crtc(struct crtc_config *crtc, + struct igt_fb *fb_info) +{ + int bpp; + int depth; + bool enable_tiling; + int fb_id; + + bpp = 32; + depth = 24; + enable_tiling = false; + fb_id = igt_create_fb(drm_fd, crtc->mode.hdisplay, + crtc->mode.vdisplay, + igt_bpp_depth_to_drm_format(bpp, depth), + enable_tiling, fb_info); + igt_assert(fb_id > 0); +} + +static void get_mode_for_crtc(struct crtc_config *crtc, + drmModeModeInfo *mode_ret) +{ + drmModeModeInfo mode; + int i; + + /* + * First try to select a default mode that is supported by all + * connectors. + */ + for (i = 0; i < crtc->connector_count; i++) { + mode = crtc->cconfs[i].default_mode; + if (crtc_supports_mode(crtc, &mode)) + goto found; + } + + /* + * Then just fall back to find any that is supported by all + * connectors. + */ + for (i = 0; i < crtc->cconfs[0].connector->count_modes; i++) { + mode = crtc->cconfs[0].connector->modes[i]; + if (crtc_supports_mode(crtc, &mode)) + goto found; + } + + /* + * If none is found then just pick the default mode of the first + * connector and hope the other connectors can support it by scaling + * etc. + */ + mode = crtc->cconfs[0].default_mode; +found: + *mode_ret = mode; +} + +static int get_encoder_idx(drmModeRes *resources, drmModeEncoder *encoder) +{ + int i; + + for (i = 0; i < resources->count_encoders; i++) + if (resources->encoders[i] == encoder->encoder_id) + return i; + igt_assert(0); +} + +static void get_crtc_config_str(struct crtc_config *crtc, char *buf, + size_t buf_size) +{ + int pos; + int i; + + pos = snprintf(buf, buf_size, + "CRTC[%d] [Pipe %s] Mode: %s@%dHz Connectors: ", + crtc->crtc_id, kmstest_pipe_str(crtc->pipe_id), + crtc->mode.name, crtc->mode.vrefresh); + if (pos > buf_size) + return; + for (i = 0; i < crtc->connector_count; i++) { + drmModeConnector *connector = crtc->cconfs[i].connector; + + pos += snprintf(&buf[pos], buf_size - pos, + "%s%s-%d[%d]%s", i ? ", " : "", + kmstest_connector_type_str(connector->connector_type), + connector->connector_type_id, connector->connector_id, + crtc->cconfs[i].connected ? "" : " (NC)"); + if (pos > buf_size) + return; + } +} + +static void setup_crtcs(drmModeRes *resources, struct connector_config *cconf, + int connector_count, struct crtc_config *crtcs, + int *crtc_count_ret, bool *config_valid_ret) +{ + struct crtc_config *crtc; + int crtc_count; + bool config_valid; + int i; + int encoder_usage_count[resources->count_encoders]; + + i = 0; + crtc_count = 0; + crtc = crtcs; + config_valid = true; + + while (i < connector_count) { + drmModeCrtc *drm_crtc; + unsigned long encoder_mask; + int j; + + igt_assert(crtc_count < MAX_CRTCS); + + crtc->crtc_idx = cconf[i].crtc_idx; + drm_crtc = drmModeGetCrtc(drm_fd, + resources->crtcs[crtc->crtc_idx]); + crtc->crtc_id = drm_crtc->crtc_id; + drmModeFreeCrtc(drm_crtc); + crtc->pipe_id = kmstest_get_pipe_from_crtc_id(drm_fd, + crtc->crtc_id); + + crtc->connector_count = 1; + for (j = i + 1; j < connector_count; j++) + if (cconf[j].crtc_idx == crtc->crtc_idx) + crtc->connector_count++; + + crtc->cconfs = malloc(sizeof(*crtc->cconfs) * + crtc->connector_count); + igt_assert(crtc->cconfs); + + encoder_mask = 0; + for (j = 0; j < crtc->connector_count; j++) { + drmModeConnector *connector; + drmModeEncoder *encoder; + + crtc->cconfs[j] = cconf[i + j]; + connector = cconf[i + j].connector; + + /* Intel connectors have only a single encoder */ + igt_assert(connector->count_encoders == 1); + encoder = drmModeGetEncoder(drm_fd, + connector->encoders[0]); + igt_assert(encoder); + + config_valid &= !!(encoder->possible_crtcs & + (1 << crtc->crtc_idx)); + + encoder_mask |= 1 << get_encoder_idx(resources, + encoder); + config_valid &= !(encoder_mask & + ~encoder->possible_clones); + + drmModeFreeEncoder(encoder); + } + get_mode_for_crtc(crtc, &crtc->mode); + create_fb_for_crtc(crtc, &crtc->fb_info); + + i += crtc->connector_count; + crtc_count++; + crtc++; + } + + memset(encoder_usage_count, 0, sizeof(encoder_usage_count)); + for (i = 0; i < connector_count; i++) { + drmModeConnector *connector = cconf[i].connector; + drmModeEncoder *encoder; + + igt_assert(connector->count_encoders == 1); + encoder = drmModeGetEncoder(drm_fd, connector->encoders[0]); + encoder_usage_count[get_encoder_idx(resources, encoder)]++; + drmModeFreeEncoder(encoder); + } + for (i = 0; i < resources->count_encoders; i++) + if (encoder_usage_count[i] > 1) + config_valid = false; + + *crtc_count_ret = crtc_count; + *config_valid_ret = config_valid; +} + +static void cleanup_crtcs(struct crtc_config *crtcs, int crtc_count) +{ + int i; + + for (i = 0; i < crtc_count; i++) { + free(crtcs[i].cconfs); + } +} + +static uint32_t *get_connector_ids(struct crtc_config *crtc) +{ + uint32_t *ids; + int i; + + ids = malloc(sizeof(*ids) * crtc->connector_count); + igt_assert(ids); + for (i = 0; i < crtc->connector_count; i++) + ids[i] = crtc->cconfs[i].connector->connector_id; + + return ids; +} + +static void test_crtc_config(const struct test_config *tconf, + struct crtc_config *crtcs, int crtc_count) +{ + char str_buf[MAX_CRTCS][1024]; + const char *crtc_strs[MAX_CRTCS]; + struct crtc_config *crtc; + static int test_id; + bool config_failed = false; + bool connector_connected = false; + int ret = 0; + int i; + + test_id++; + + if (filter_test_id && filter_test_id != test_id) + return; + + igt_info(" Test id#%d CRTC count %d\n", test_id, crtc_count); + + for (i = 0; i < crtc_count; i++) { + get_crtc_config_str(&crtcs[i], str_buf[i], sizeof(str_buf[i])); + crtc_strs[i] = &str_buf[i][0]; + } + + if (dry_run) { + for (i = 0; i < crtc_count; i++) + igt_info(" %s\n", crtc_strs[i]); + return; + } + + for (i = 0; i < crtc_count; i++) { + uint32_t *ids; + int j; + + crtc = &crtcs[i]; + + igt_info(" %s\n", crtc_strs[i]); + + create_fb_for_crtc(crtc, &crtc->fb_info); + paint_fb(&crtc->fb_info, tconf->name, crtc_strs, crtc_count, i); + + ids = get_connector_ids(crtc); + ret = drmModeSetCrtc(drm_fd, crtc->crtc_id, + crtc->fb_info.fb_id, 0, 0, ids, + crtc->connector_count, &crtc->mode); + free(ids); + + if (ret < 0) { + igt_assert(errno == EINVAL); + config_failed = true; + } + + for (j = 0; j < crtc->connector_count; j++) + connector_connected |= crtc->cconfs[j].connected; + } + + igt_assert(config_failed == !!(tconf->flags & TEST_INVALID)); + + if (ret == 0 && connector_connected && !(tconf->flags & TEST_INVALID)) + sleep(5); + + for (i = 0; i < crtc_count; i++) { + if (crtcs[i].fb_info.fb_id) { + drmModeSetCrtc(drm_fd, crtcs[i].crtc_id, 0, 0, 0, NULL, + 0, NULL); + drmModeRmFB(drm_fd, crtcs[i].fb_info.fb_id); + crtcs[i].fb_info.fb_id = 0; + } + } + + return; +} + +static void test_one_combination(const struct test_config *tconf, + struct connector_config *cconfs, + int connector_count) +{ + struct crtc_config crtcs[MAX_CRTCS]; + int crtc_count; + bool config_valid; + + setup_crtcs(tconf->resources, cconfs, connector_count, crtcs, + &crtc_count, &config_valid); + + if (config_valid == !(tconf->flags & TEST_INVALID)) + test_crtc_config(tconf, crtcs, crtc_count); + + cleanup_crtcs(crtcs, crtc_count); +} + +static int assign_crtc_to_connectors(const struct test_config *tconf, + int *crtc_idxs, int connector_count, + struct connector_config *cconfs) +{ + unsigned long crtc_idx_mask; + int i; + + crtc_idx_mask = 0; + for (i = 0; i < connector_count; i++) { + int crtc_idx = crtc_idxs[i]; + + if ((tconf->flags & TEST_SINGLE_CRTC_CLONE) && + crtc_idx_mask & ~(1 << crtc_idx)) + return -1; + + if ((tconf->flags & TEST_EXCLUSIVE_CRTC_CLONE) && + crtc_idx_mask & (1 << crtc_idx)) + return -1; + + crtc_idx_mask |= 1 << crtc_idx; + + cconfs[i].crtc_idx = crtc_idx; + } + + return 0; +} + +static int get_one_connector(drmModeRes *resources, int connector_id, + struct connector_config *cconf) +{ + drmModeConnector *connector; + drmModeModeInfo mode; + + connector = drmModeGetConnector(drm_fd, connector_id); + igt_assert(connector); + cconf->connector = connector; + + cconf->connected = connector->connection == DRM_MODE_CONNECTED; + + /* + * For DP/eDP we need a connected sink, since mode setting depends + * on successful link training and retrieved DPCD parameters. + */ + switch (connector->connector_type) { + case DRM_MODE_CONNECTOR_DisplayPort: + case DRM_MODE_CONNECTOR_eDP: + if (!cconf->connected) { + drmModeFreeConnector(connector); + return -1; + } + } + + if (cconf->connected) { + if (kmstest_get_connector_default_mode(drm_fd, connector, + &mode) < 0) + mode = mode_640_480; + } else { + mode = mode_640_480; + } + + cconf->default_mode = mode; + + return 0; +} + +static int get_connectors(drmModeRes *resources, int *connector_idxs, + int connector_count, struct connector_config *cconfs) +{ + int i; + + for (i = 0; i < connector_count; i++) { + int connector_idx; + int connector_id; + + connector_idx = connector_idxs[i]; + igt_assert(connector_idx < resources->count_connectors); + connector_id = resources->connectors[connector_idx]; + + if (get_one_connector(resources, connector_id, &cconfs[i]) < 0) + goto err; + + } + + return 0; + +err: + while (i--) + drmModeFreeConnector(cconfs[i].connector); + + return -1; +} + +static void free_connectors(struct connector_config *cconfs, + int connector_count) +{ + int i; + + for (i = 0; i < connector_count; i++) + drmModeFreeConnector(cconfs[i].connector); +} + +struct combination { + int elems[MAX_COMBINATION_ELEMS]; +}; + +struct combination_set { + int count; + struct combination items[MAX_COMBINATION_COUNT]; +}; + +/* + * Get all possible selection of k elements from n elements with or without + * repetitions. + */ +static void iterate_combinations(int n, int k, bool allow_repetitions, + int depth, int base, struct combination *comb, + struct combination_set *set) +{ + int v; + + if (!k) { + igt_assert(set->count < ARRAY_SIZE(set->items)); + set->items[set->count++] = *comb; + return; + } + + for (v = base; v < n; v++) { + comb->elems[depth] = v; + iterate_combinations(n, k - 1, allow_repetitions, + depth + 1, allow_repetitions ? 0 : v + 1, + comb, set); + } + +} + +static void get_combinations(int n, int k, bool allow_repetitions, + struct combination_set *set) +{ + struct combination comb; + + igt_assert(k <= ARRAY_SIZE(set->items[0].elems)); + set->count = 0; + iterate_combinations(n, k, allow_repetitions, 0, 0, &comb, set); +} + +static void test_combinations(const struct test_config *tconf, + int connector_count) +{ + struct combination_set connector_combs; + struct combination_set crtc_combs; + struct connector_config *cconfs; + int i; + + get_combinations(tconf->resources->count_connectors, connector_count, + false, &connector_combs); + get_combinations(tconf->resources->count_crtcs, connector_count, + true, &crtc_combs); + + igt_info("Testing: %s %d connector combinations\n", tconf->name, + connector_count); + for (i = 0; i < connector_combs.count; i++) { + int *connector_idxs; + int ret; + int j; + + cconfs = malloc(sizeof(*cconfs) * connector_count); + igt_assert(cconfs); + + connector_idxs = &connector_combs.items[i].elems[0]; + ret = get_connectors(tconf->resources, connector_idxs, + connector_count, cconfs); + if (ret < 0) + goto free_cconfs; + + for (j = 0; j < crtc_combs.count; j++) { + int *crtc_idxs = &crtc_combs.items[j].elems[0]; + ret = assign_crtc_to_connectors(tconf, crtc_idxs, + connector_count, + cconfs); + if (ret < 0) + continue; + + test_one_combination(tconf, cconfs, connector_count); + } + + free_connectors(cconfs, connector_count); +free_cconfs: + free(cconfs); + } +} + +static void run_test(const struct test_config *tconf) +{ + int connector_num; + + connector_num = tconf->flags & TEST_CLONE ? 2 : 1; + for (; connector_num <= tconf->resources->count_crtcs; connector_num++) + test_combinations(tconf, connector_num); +} + +static int opt_handler(int opt, int opt_index) +{ + switch (opt) { + case 'd': + dry_run = true; + break; + case 't': + filter_test_id = atoi(optarg); + break; + default: + igt_assert(0); + } + + return 0; +} + +int main(int argc, char **argv) +{ + const struct { + enum test_flags flags; + const char *name; + } tests[] = { + { TEST_CLONE | TEST_SINGLE_CRTC_CLONE, + "clone-single-crtc" }, + { TEST_INVALID | TEST_CLONE | TEST_SINGLE_CRTC_CLONE, + "invalid-clone-single-crtc" }, + { TEST_INVALID | TEST_CLONE | TEST_EXCLUSIVE_CRTC_CLONE, + "invalid-clone-exclusive-crtc" }, + { TEST_CLONE | TEST_EXCLUSIVE_CRTC_CLONE, + "clone-exclusive-crtc" }, + }; + const char *help_str = + " -d\t\tDon't run any test, only print what would be done. (still needs DRM access)\n" + " -t <test id>\tRun only the test with this id."; + int i; + int ret; + + ret = igt_subtest_init_parse_opts(argc, argv, "dt:", NULL, help_str, + opt_handler); + if (ret < 0) + return ret == -1 ? 0 : ret; + + igt_skip_on_simulation(); + + igt_assert_f(!(dry_run && filter_test_id), + "only one of -d and -t is accepted\n"); + + igt_fixture { + drm_fd = drm_open_any(); + if (!dry_run) + igt_set_vt_graphics_mode(); + + drm_resources = drmModeGetResources(drm_fd); + igt_assert(drm_resources); + } + + for (i = 0; i < ARRAY_SIZE(tests); i++) { + igt_subtest(tests[i].name) { + struct test_config tconf = { + .flags = tests[i].flags, + .name = tests[i].name, + .resources = drm_resources, + }; + run_test(&tconf); + } + } + + igt_fixture { + drmModeFreeResources(drm_resources); + + close(drm_fd); + } + + igt_exit(); +} diff --git a/tests/kms_sink_crc_basic.c b/tests/kms_sink_crc_basic.c new file mode 100644 index 00000000..087b79db --- /dev/null +++ b/tests/kms_sink_crc_basic.c @@ -0,0 +1,191 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include <errno.h> +#include <limits.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> + +#include "drm_fourcc.h" + +#include "drmtest.h" +#include "igt_debugfs.h" +#include "igt_kms.h" + +enum color { + WHITE, + BLACK, + NUM_COLORS, +}; + +typedef struct { + struct kmstest_connector_config config; + struct igt_fb fb; +} connector_t; + +typedef struct { + int drm_fd; + drmModeRes *resources; +} data_t; + +static void get_crc(char *crc) { + int ret; + FILE *file = fopen("/sys/kernel/debug/dri/0/i915_sink_crc_eDP1", "r"); + igt_require(file); + + ret = fscanf(file, "%s\n", crc); + igt_require(ret > 0); + + fclose(file); +} + +static uint32_t create_fb(data_t *data, + int w, int h, + double r, double g, double b, + struct igt_fb *fb) +{ + cairo_t *cr; + uint32_t fb_id; + + fb_id = igt_create_fb(data->drm_fd, w, h, + DRM_FORMAT_XRGB8888, false, fb); + igt_assert(fb_id); + + cr = igt_get_cairo_ctx(data->drm_fd, fb); + igt_paint_color(cr, 0, 0, w, h, r, g, b); + igt_assert(cairo_status(cr) == 0); + + return fb_id; +} + +static bool +connector_set_mode(data_t *data, connector_t *connector, drmModeModeInfo *mode, + enum color crtc_color) +{ + struct kmstest_connector_config *config = &connector->config; + unsigned int fb_id; + int ret; + + if (crtc_color == WHITE) + fb_id = create_fb(data, mode->hdisplay, mode->vdisplay, + 1.0, 1.0, 1.0, &connector->fb); + else + fb_id = create_fb(data, mode->hdisplay, mode->vdisplay, + 0.0, 0.0, 0.0, &connector->fb); + igt_assert(fb_id); + + ret = drmModeSetCrtc(data->drm_fd, + config->crtc->crtc_id, + connector->fb.fb_id, + 0, 0, /* x, y */ + &config->connector->connector_id, + 1, + mode); + igt_assert(ret == 0); + + return 0; +} + +static void basic_sink_crc_check(data_t *data, uint32_t connector_id) +{ + connector_t connector; + int ret; + char ref_crc_white[12]; + char ref_crc_black[12]; + char crc_check[12]; + + ret = kmstest_get_connector_config(data->drm_fd, + connector_id, + 1 << 0, + &connector.config); + igt_require(ret == 0); + + /*Go White*/ + connector_set_mode(data, &connector, &connector.config.default_mode, WHITE); + + /* get reference crc for white color */ + get_crc(ref_crc_white); + + /* Go Black */ + connector_set_mode(data, &connector, &connector.config.default_mode, BLACK); + + /* get reference crc for black color */ + get_crc(ref_crc_black); + + igt_assert(strcmp(ref_crc_black, ref_crc_white) != 0); + + /*Go White again*/ + connector_set_mode(data, &connector, &connector.config.default_mode, WHITE); + + get_crc(crc_check); + igt_assert(strcmp(crc_check, ref_crc_white) == 0); + + /* Go Black again */ + connector_set_mode(data, &connector, &connector.config.default_mode, BLACK); + + get_crc(crc_check); + igt_assert(strcmp(crc_check, ref_crc_black) == 0); + + kmstest_free_connector_config(&connector.config); +} + +static void run_test(data_t *data) +{ + int i; + drmModeConnectorPtr c; + uint32_t connector_id = 0; + + for (i = 0; i < data->resources->count_connectors; i++) { + connector_id = data->resources->connectors[i]; + c = drmModeGetConnector(data->drm_fd, connector_id); + + if (c->connector_type != DRM_MODE_CONNECTOR_eDP || + c->connection != DRM_MODE_CONNECTED) + continue; + + basic_sink_crc_check(data, connector_id); + return; + } + + igt_skip("no eDP with CRC support found\n"); +} + +igt_simple_main +{ + data_t data = {}; + + igt_skip_on_simulation(); + + data.drm_fd = drm_open_any(); + + igt_set_vt_graphics_mode(); + + data.resources = drmModeGetResources(data.drm_fd); + igt_assert(data.resources); + + run_test(&data); + + drmModeFreeResources(data.resources); +} diff --git a/tests/sysfs_edid_timing b/tests/kms_sysfs_edid_timing index 3a8c6c0e..ec704f67 100755 --- a/tests/sysfs_edid_timing +++ b/tests/kms_sysfs_edid_timing @@ -1,10 +1,15 @@ -#!/bin/sh +#!/bin/bash # # This check the time we take to read the content of all the possible connectors. # Without the edid -ENXIO patch (http://permalink.gmane.org/gmane.comp.video.dri.devel/62083), # we sometimes take a *really* long time. So let's just check for some reasonable timing here # +DRM_LIB_ALLOW_NO_MASTER=1 + +SOURCE_DIR="$( dirname "${BASH_SOURCE[0]}" )" +. $SOURCE_DIR/drm_lib.sh + TIME1=$(date +%s%N) cat $(find /sys/devices/|grep drm | grep /status) > /dev/null TIME2=$(date +%s%N) diff --git a/tests/pm_lpsp.c b/tests/pm_lpsp.c new file mode 100644 index 00000000..9d3884c0 --- /dev/null +++ b/tests/pm_lpsp.c @@ -0,0 +1,280 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Author: Paulo Zanoni <paulo.r.zanoni@intel.com> + * + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +#include "drmtest.h" +#include "igt_kms.h" +#include "intel_io.h" +#include "intel_chipset.h" + +/* We know that if we don't enable audio runtime PM, snd_hda_intel will never + * release its power well refcount, and we'll never reach the LPSP sate. OTOH + * there's no guarantee that it will release the power well if we enable runtime + * PM, but at least we can try. We don't have any assertions since the user may + * not even have snd_hda_intel loaded, which is not a problem. */ +static void disable_audio_runtime_pm(void) +{ + int fd; + + fd = open("/sys/module/snd_hda_intel/parameters/power_save", O_WRONLY); + if (fd >= 0) { + write(fd, "1\n", 2); + close(fd); + } + fd = open("/sys/bus/pci/devices/0000:00:03.0/power/control", O_WRONLY); + if (fd >= 0) { + write(fd, "auto\n", 5); + close(fd); + } + /* Give some time for it to react. */ + sleep(1); +} + +static bool supports_lpsp(uint32_t devid) +{ + return IS_HASWELL(devid) || IS_BROADWELL(devid); +} + +static bool lpsp_is_enabled(int drm_fd) +{ + uint32_t val; + + val = INREG(HSW_PWR_WELL_CTL2); + return !(val & HSW_PWR_WELL_STATE_ENABLED); +} + +static void disable_all_screens(int drm_fd, drmModeResPtr drm_resources) +{ + int i, rc; + + for (i = 0; i < drm_resources->count_crtcs; i++) { + rc = drmModeSetCrtc(drm_fd, drm_resources->crtcs[i], -1, 0, 0, + NULL, 0, NULL); + igt_assert(rc == 0); + } +} + +/* The LPSP mode is all about an enabled pipe, but we expect to also be in the + * low power mode when no pipes are enabled, so do this check anyway. */ +static void screens_disabled_subtest(int drm_fd, drmModeResPtr drm_res) +{ + disable_all_screens(drm_fd, drm_res); + igt_assert(lpsp_is_enabled(drm_fd)); +} + +static uint32_t create_fb(int drm_fd, int width, int height) +{ + struct igt_fb fb; + cairo_t *cr; + uint32_t buffer_id; + + buffer_id = igt_create_fb(drm_fd, width, height, + DRM_FORMAT_XRGB8888, + false, &fb); + cr = igt_get_cairo_ctx(drm_fd, &fb); + igt_paint_test_pattern(cr, width, height); + cairo_destroy(cr); + + return buffer_id; +} + +static void edp_subtest(int drm_fd, drmModeResPtr drm_res, + drmModeConnectorPtr *drm_connectors, uint32_t devid, + bool use_panel_fitter) +{ + int i, rc; + uint32_t connector_id = 0, crtc_id = 0, buffer_id = 0; + drmModeModeInfoPtr mode = NULL; + drmModeModeInfo std_1024_mode = { + .clock = 65000, + .hdisplay = 1024, + .hsync_start = 1048, + .hsync_end = 1184, + .htotal = 1344, + .vtotal = 806, + .hskew = 0, + .vdisplay = 768, + .vsync_start = 771, + .vsync_end = 777, + .vtotal = 806, + .vscan = 0, + .vrefresh = 60, + .flags = 0xA, + .type = 0x40, + .name = "Custom 1024x768", + }; + + disable_all_screens(drm_fd, drm_res); + + for (i = 0; i < drm_res->count_connectors; i++) { + drmModeConnectorPtr c = drm_connectors[i]; + + if (c->connector_type != DRM_MODE_CONNECTOR_eDP) + continue; + if (c->connection != DRM_MODE_CONNECTED) + continue; + + if (!use_panel_fitter && c->count_modes) { + connector_id = c->connector_id; + mode = &c->modes[0]; + break; + } + if (use_panel_fitter) { + connector_id = c->connector_id; + + /* This is one of the modes Xorg creates for panels, so + * it should work just fine. Notice that Gens that + * support LPSP are too new for panels with native + * 1024x768 resolution, so this should force the panel + * fitter. */ + igt_assert(c->count_modes && + c->modes[0].hdisplay > 1024); + igt_assert(c->count_modes && + c->modes[0].vdisplay > 768); + mode = &std_1024_mode; + break; + } + } + igt_require(connector_id); + + crtc_id = drm_res->crtcs[0]; + buffer_id = create_fb(drm_fd, mode->hdisplay, mode->vdisplay); + + igt_assert(crtc_id); + igt_assert(buffer_id); + igt_assert(connector_id); + igt_assert(mode); + + rc = drmModeSetCrtc(drm_fd, crtc_id, buffer_id, 0, 0, &connector_id, 1, + mode); + igt_assert(rc == 0); + + if (use_panel_fitter) { + if (IS_HASWELL(devid)) + igt_assert(!lpsp_is_enabled(drm_fd)); + else + igt_assert(lpsp_is_enabled(drm_fd)); + } else { + igt_assert(lpsp_is_enabled(drm_fd)); + } +} + +static void non_edp_subtest(int drm_fd, drmModeResPtr drm_res, + drmModeConnectorPtr *drm_connectors) +{ + int i, rc; + uint32_t connector_id = 0, crtc_id = 0, buffer_id = 0; + drmModeModeInfoPtr mode = NULL; + + disable_all_screens(drm_fd, drm_res); + + for (i = 0; i < drm_res->count_connectors; i++) { + drmModeConnectorPtr c = drm_connectors[i]; + + if (c->connector_type == DRM_MODE_CONNECTOR_eDP) + continue; + if (c->connection != DRM_MODE_CONNECTED) + continue; + + if (c->count_modes) { + connector_id = c->connector_id; + mode = &c->modes[0]; + break; + } + } + igt_require(connector_id); + + crtc_id = drm_res->crtcs[0]; + buffer_id = create_fb(drm_fd, mode->hdisplay, mode->vdisplay); + + igt_assert(crtc_id); + igt_assert(buffer_id); + igt_assert(connector_id); + igt_assert(mode); + + rc = drmModeSetCrtc(drm_fd, crtc_id, buffer_id, 0, 0, &connector_id, 1, + mode); + igt_assert(rc == 0); + + igt_assert(!lpsp_is_enabled(drm_fd)); +} + +#define MAX_CONNECTORS 32 + +int drm_fd; +uint32_t devid; +drmModeResPtr drm_res; +drmModeConnectorPtr drm_connectors[MAX_CONNECTORS]; + +igt_main +{ + igt_fixture { + int i; + + drm_fd = drm_open_any(); + igt_require(drm_fd >= 0); + + devid = intel_get_drm_devid(drm_fd); + + drm_res = drmModeGetResources(drm_fd); + igt_assert(drm_res->count_connectors <= MAX_CONNECTORS); + + for (i = 0; i < drm_res->count_connectors; i++) + drm_connectors[i] = drmModeGetConnector(drm_fd, + drm_res->connectors[i]); + + disable_audio_runtime_pm(); + + igt_require(supports_lpsp(devid)); + + intel_register_access_init(intel_get_pci_device(), 0); + + igt_set_vt_graphics_mode(); + } + + igt_subtest("screens-disabled") + screens_disabled_subtest(drm_fd, drm_res); + igt_subtest("edp-native") + edp_subtest(drm_fd, drm_res, drm_connectors, devid, false); + igt_subtest("edp-panel-fitter") + edp_subtest(drm_fd, drm_res, drm_connectors, devid, true); + igt_subtest("non-edp") + non_edp_subtest(drm_fd, drm_res, drm_connectors); + + igt_fixture { + int i; + + intel_register_access_fini(); + for (i = 0; i < drm_res->count_connectors; i++) + drmModeFreeConnector(drm_connectors[i]); + drmModeFreeResources(drm_res); + close(drm_fd); + } +} diff --git a/tests/pm_psr.c b/tests/pm_psr.c new file mode 100644 index 00000000..3ab7e7a0 --- /dev/null +++ b/tests/pm_psr.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Rodrigo Vivi <rodrigo.vivi@intel.com> + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> + +#include "drmtest.h" + +#define SLEEP_DURATION 5000 // in milliseconds + +static int get_perf(const char *path) +{ + int ret, perf; + FILE *file; + char str[4]; + + file = fopen(path, "r"); + igt_assert(file); + + ret = fscanf(file, "Sink_Support: %s\n", str); + igt_skip_on_f(ret == 0, + "i915_edp_psr_status format not supported by this test case\n"); + igt_require(strcmp(str, "yes") == 0); + ret = fscanf(file, "Source_OK: %s\n", str); + igt_assert(ret != 0); + + igt_require(strcmp(str, "yes") == 0); + + ret = fscanf(file, "Enabled: %s\n", str); + igt_assert(ret != 0); + igt_assert(strcmp(str, "yes") == 0); + + ret = fscanf(file, "Performance_Counter: %i", &perf); + igt_assert(ret != 0); + + igt_assert(perf); + + fclose(file); + return perf; +} + +igt_simple_main +{ + int ret, perf1, perf2; + int device = drm_get_card(); + char *path; + + igt_skip_on_simulation(); + + ret = asprintf(&path, "/sys/kernel/debug/dri/%d/i915_edp_psr_status", device); + igt_assert(ret != -1); + + perf1 = get_perf(path); + sleep(SLEEP_DURATION / 1000); + perf2 = get_perf(path); + + igt_assert_f(perf1 != perf2, + "Unable to enter PSR state again\n"); +} diff --git a/tests/pm_rc6_residency.c b/tests/pm_rc6_residency.c new file mode 100644 index 00000000..550e3adf --- /dev/null +++ b/tests/pm_rc6_residency.c @@ -0,0 +1,169 @@ +/* + * Copyright © 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Ben Widawsky <ben@bwidawsk.net> + * + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> + +#include "drmtest.h" + +#define NUMBER_OF_RC6_RESIDENCY 3 +#define SLEEP_DURATION 3000 // in milliseconds +#define RC6_FUDGE 900 // in milliseconds + + +static unsigned int readit(const char *path) +{ + unsigned int ret; + int scanned; + + FILE *file; + file = fopen(path, "r"); + if (file == NULL) { + fprintf(stderr, "Couldn't open %s (%d)\n", path, errno); + abort(); + } + scanned = fscanf(file, "%u", &ret); + igt_assert(scanned == 1); + + fclose(file); + + return ret; +} + +static void read_rc6_residency( int value[], const char *name_of_rc6_residency[]) +{ + const int device = drm_get_card(); + char *path ; + int ret; + FILE *file; + + /* For some reason my ivb isn't idle even after syncing up with the gpu. + * Let's add a sleept just to make it happy. */ + sleep(5); + + ret = asprintf(&path, "/sys/class/drm/card%d/power/rc6_enable", device); + igt_assert(ret != -1); + + file = fopen(path, "r");//open + igt_require(file); + + /* claim success if no rc6 enabled. */ + if (readit(path) == 0) + igt_success(); + + for(unsigned int i = 0; i < 6; i++) + { + if(i == 3) + sleep(SLEEP_DURATION / 1000); + ret = asprintf(&path, "/sys/class/drm/card%d/power/%s_residency_ms",device,name_of_rc6_residency[i % 3] ); + igt_assert(ret != -1); + value[i] = readit(path); + } + free(path); +} + +static void rc6_residency_counter(int value[],const char * name_of_rc6_residency[]) +{ + unsigned int flag_counter,flag_support; + double counter_result = 0; + flag_counter = 0; + flag_support = 0; + + for(int flag = NUMBER_OF_RC6_RESIDENCY-1; flag >= 0 ; flag --) + { + unsigned int tmp_counter, tmp_support; + double counter; + counter = ((double)value[flag + 3] - (double)value[flag]) /(double) SLEEP_DURATION; + + if( counter > 0.9 ){ + counter_result = counter; + tmp_counter = 1; + } + else + tmp_counter = 0; + + if( value [flag + 3] == 0){ + tmp_support = 0; + printf("This machine doesn't support %s\n",name_of_rc6_residency[flag]); + } + else + tmp_support = 1; + + flag_counter = flag_counter + tmp_counter; + flag_counter = flag_counter << 1; + + flag_support = flag_support + tmp_support; + flag_support = flag_support << 1; + } + + printf("The residency counter : %f \n", counter_result); + + igt_assert_f(flag_counter != 0 , "The RC6 residency counter is not good.\n"); + igt_assert_f(flag_support != 0 , "This machine doesn't support any RC6 state!\n"); + igt_assert_f(counter_result <=1 , "Debug files must be wrong \n"); + + printf("This machine entry %s state.\n", name_of_rc6_residency[(flag_counter / 2) - 1]); +} + +static void rc6_residency_check(int value[]) +{ + unsigned int diff; + diff = (value[3] - value[0]) + + (value[4] - value[1]) + + (value[5] - value[2]); + + igt_assert_f(diff <= (SLEEP_DURATION + RC6_FUDGE),"Diff was too high. That is unpossible\n"); + igt_assert_f(diff >= (SLEEP_DURATION - RC6_FUDGE),"GPU was not in RC6 long enough. Check that " + "the GPU is as idle as possible(ie. no X, " + "running and running no other tests)\n"); +} + +igt_main +{ + int value[6]; + int fd; + const char * name_of_rc6_residency[3]={"rc6","rc6p","rc6pp"}; + + igt_skip_on_simulation(); + + /* Use drm_open_any to verify device existence */ + fd = drm_open_any(); + close(fd); + + read_rc6_residency(value, name_of_rc6_residency); + + igt_subtest("rc6-residency-check") + rc6_residency_check(value); + + igt_subtest("rc6-residency-counter") + rc6_residency_counter(value, name_of_rc6_residency); + +} diff --git a/tests/pm_rpm.c b/tests/pm_rpm.c new file mode 100644 index 00000000..323e0729 --- /dev/null +++ b/tests/pm_rpm.c @@ -0,0 +1,1497 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Paulo Zanoni <paulo.r.zanoni@intel.com> + * + */ + +#include <stdio.h> +#include <stdint.h> +#include <stdbool.h> +#include <string.h> + +#include <unistd.h> +#include <fcntl.h> +#include <dirent.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <linux/i2c.h> +#include <linux/i2c-dev.h> + +#include <drm.h> + +#include "drmtest.h" +#include "intel_batchbuffer.h" +#include "intel_io.h" +#include "intel_chipset.h" +#include "ioctl_wrappers.h" +#include "igt_aux.h" +#include "igt_kms.h" +#include "igt_debugfs.h" + +#define MSR_PC8_RES 0x630 +#define MSR_PC9_RES 0x631 +#define MSR_PC10_RES 0x632 + +#define MAX_CONNECTORS 32 +#define MAX_ENCODERS 32 +#define MAX_CRTCS 16 + +#define POWER_DIR "/sys/devices/pci0000:00/0000:00:02.0/power" + +enum pc8_status { + PC8_ENABLED, + PC8_DISABLED +}; + +enum screen_type { + SCREEN_TYPE_LPSP, + SCREEN_TYPE_NON_LPSP, + SCREEN_TYPE_ANY, +}; + +/* Wait flags */ +#define DONT_WAIT 0 +#define WAIT_STATUS 1 +#define WAIT_PC8_RES 2 +#define WAIT_EXTRA 4 +#define USE_DPMS 8 + +int drm_fd, msr_fd, pm_status_fd, pc8_status_fd; +bool has_runtime_pm, has_pc8; +struct mode_set_data ms_data; +struct scanout_fb *fbs = NULL; + +/* Stuff used when creating FBs and mode setting. */ +struct mode_set_data { + drmModeResPtr res; + drmModeConnectorPtr connectors[MAX_CONNECTORS]; + drmModePropertyBlobPtr edids[MAX_CONNECTORS]; + + uint32_t devid; +}; + +/* Stuff we query at different times so we can compare. */ +struct compare_data { + drmModeResPtr res; + drmModeEncoderPtr encoders[MAX_ENCODERS]; + drmModeConnectorPtr connectors[MAX_CONNECTORS]; + drmModeCrtcPtr crtcs[MAX_CRTCS]; + drmModePropertyBlobPtr edids[MAX_CONNECTORS]; +}; + +/* During the stress tests we want to be as fast as possible, so use pre-created + * FBs instead of creating them again and again. */ +struct scanout_fb { + uint32_t handle; + int width; + int height; + struct scanout_fb *next; +}; + +/* If the read fails, then the machine doesn't support PC8+ residencies. */ +static bool supports_pc8_plus_residencies(void) +{ + int rc; + uint64_t val; + + rc = pread(msr_fd, &val, sizeof(uint64_t), MSR_PC8_RES); + if (rc != sizeof(val)) + return false; + rc = pread(msr_fd, &val, sizeof(uint64_t), MSR_PC9_RES); + if (rc != sizeof(val)) + return false; + rc = pread(msr_fd, &val, sizeof(uint64_t), MSR_PC10_RES); + if (rc != sizeof(val)) + return false; + + return true; +} + +static uint64_t get_residency(uint32_t type) +{ + int rc; + uint64_t ret; + + rc = pread(msr_fd, &ret, sizeof(uint64_t), type); + igt_assert(rc == sizeof(ret)); + + return ret; +} + +static bool pc8_plus_residency_changed(unsigned int timeout_sec) +{ + unsigned int i; + uint64_t res_pc8, res_pc9, res_pc10; + int to_sleep = 100 * 1000; + + res_pc8 = get_residency(MSR_PC8_RES); + res_pc9 = get_residency(MSR_PC9_RES); + res_pc10 = get_residency(MSR_PC10_RES); + + for (i = 0; i < timeout_sec * 1000 * 1000; i += to_sleep) { + if (res_pc8 != get_residency(MSR_PC8_RES) || + res_pc9 != get_residency(MSR_PC9_RES) || + res_pc10 != get_residency(MSR_PC10_RES)) { + return true; + } + usleep(to_sleep); + } + + return false; +} + +static enum pc8_status get_pc8_status(void) +{ + ssize_t n_read; + char buf[150]; /* The whole file has less than 100 chars. */ + + lseek(pc8_status_fd, 0, SEEK_SET); + n_read = read(pc8_status_fd, buf, ARRAY_SIZE(buf)); + igt_assert(n_read >= 0); + buf[n_read] = '\0'; + + if (strstr(buf, "\nEnabled: yes\n")) + return PC8_ENABLED; + else + return PC8_DISABLED; +} + +static bool wait_for_pc8_status(enum pc8_status status) +{ + int i; + int hundred_ms = 100 * 1000, ten_s = 10 * 1000 * 1000; + + for (i = 0; i < ten_s; i += hundred_ms) { + if (get_pc8_status() == status) + return true; + + usleep(hundred_ms); + } + + return false; +} + +static bool wait_for_suspended(void) +{ + if (has_pc8 && !has_runtime_pm) + return wait_for_pc8_status(PC8_ENABLED); + else + return igt_wait_for_pm_status(IGT_RUNTIME_PM_STATUS_SUSPENDED); +} + +static bool wait_for_active(void) +{ + if (has_pc8 && !has_runtime_pm) + return wait_for_pc8_status(PC8_DISABLED); + else + return igt_wait_for_pm_status(IGT_RUNTIME_PM_STATUS_ACTIVE); +} + +static void disable_all_screens_dpms(struct mode_set_data *data) +{ + int i; + + for (i = 0; i < data->res->count_connectors; i++) { + drmModeConnectorPtr c = data->connectors[i]; + + kmstest_set_connector_dpms(drm_fd, c, DRM_MODE_DPMS_OFF); + } +} + +static void disable_all_screens(struct mode_set_data *data) +{ + int i, rc; + + for (i = 0; i < data->res->count_crtcs; i++) { + rc = drmModeSetCrtc(drm_fd, data->res->crtcs[i], -1, 0, 0, + NULL, 0, NULL); + igt_assert(rc == 0); + } +} + +static struct scanout_fb *create_fb(struct mode_set_data *data, int width, + int height) +{ + struct scanout_fb *fb_info; + struct igt_fb fb; + cairo_t *cr; + + fb_info = malloc(sizeof(struct scanout_fb)); + igt_assert(fb_info); + + fb_info->handle = igt_create_fb(drm_fd, width, height, + DRM_FORMAT_XRGB8888, + false, &fb); + fb_info->width = width; + fb_info->height = height; + fb_info->next = NULL; + + cr = igt_get_cairo_ctx(drm_fd, &fb); + igt_paint_test_pattern(cr, width, height); + cairo_destroy(cr); + + return fb_info; +} + +static uint32_t get_fb(struct mode_set_data *data, int width, int height) +{ + struct scanout_fb *fb; + + if (!fbs) { + fbs = create_fb(data, width, height); + return fbs->handle; + } + + for (fb = fbs; fb != NULL; fb = fb->next) { + if (fb->width == width && fb->height == height) + return fb->handle; + + if (!fb->next) { + fb->next = create_fb(data, width, height); + return fb->next->handle; + } + } + igt_assert(false); +} + +static bool enable_one_screen_with_type(struct mode_set_data *data, + enum screen_type type) +{ + uint32_t crtc_id = 0, buffer_id = 0, connector_id = 0; + drmModeModeInfoPtr mode = NULL; + int i, rc; + + for (i = 0; i < data->res->count_connectors; i++) { + drmModeConnectorPtr c = data->connectors[i]; + + if (type == SCREEN_TYPE_LPSP && + c->connector_type != DRM_MODE_CONNECTOR_eDP) + continue; + + if (type == SCREEN_TYPE_NON_LPSP && + c->connector_type == DRM_MODE_CONNECTOR_eDP) + continue; + + if (c->connection == DRM_MODE_CONNECTED && c->count_modes) { + connector_id = c->connector_id; + mode = &c->modes[0]; + break; + } + } + + if (connector_id == 0) + return false; + + crtc_id = data->res->crtcs[0]; + buffer_id = get_fb(data, mode->hdisplay, mode->vdisplay); + + igt_assert(crtc_id); + igt_assert(buffer_id); + igt_assert(connector_id); + igt_assert(mode); + + rc = drmModeSetCrtc(drm_fd, crtc_id, buffer_id, 0, 0, &connector_id, + 1, mode); + igt_assert(rc == 0); + + return true; +} + +static void enable_one_screen(struct mode_set_data *data) +{ + /* SKIP if there are no connected screens. */ + igt_require(enable_one_screen_with_type(data, SCREEN_TYPE_ANY)); +} + +static drmModePropertyBlobPtr get_connector_edid(drmModeConnectorPtr connector, + int index) +{ + unsigned int i; + drmModeObjectPropertiesPtr props; + drmModePropertyBlobPtr ret = NULL; + + props = drmModeObjectGetProperties(drm_fd, connector->connector_id, + DRM_MODE_OBJECT_CONNECTOR); + + for (i = 0; i < props->count_props; i++) { + drmModePropertyPtr prop = drmModeGetProperty(drm_fd, + props->props[i]); + + if (strcmp(prop->name, "EDID") == 0) { + igt_assert(prop->flags & DRM_MODE_PROP_BLOB); + igt_assert(prop->count_blobs == 0); + ret = drmModeGetPropertyBlob(drm_fd, + props->prop_values[i]); + } + + drmModeFreeProperty(prop); + } + + drmModeFreeObjectProperties(props); + return ret; +} + +static void init_mode_set_data(struct mode_set_data *data) +{ + int i; + + data->res = drmModeGetResources(drm_fd); + igt_assert(data->res); + igt_assert(data->res->count_connectors <= MAX_CONNECTORS); + + for (i = 0; i < data->res->count_connectors; i++) { + data->connectors[i] = drmModeGetConnector(drm_fd, + data->res->connectors[i]); + data->edids[i] = get_connector_edid(data->connectors[i], i); + } + + data->devid = intel_get_drm_devid(drm_fd); + + igt_set_vt_graphics_mode(); +} + +static void fini_mode_set_data(struct mode_set_data *data) +{ + int i; + + for (i = 0; i < data->res->count_connectors; i++) { + drmModeFreeConnector(data->connectors[i]); + drmModeFreePropertyBlob(data->edids[i]); + } + drmModeFreeResources(data->res); +} + +static void get_drm_info(struct compare_data *data) +{ + int i; + + data->res = drmModeGetResources(drm_fd); + igt_assert(data->res); + + igt_assert(data->res->count_connectors <= MAX_CONNECTORS); + igt_assert(data->res->count_encoders <= MAX_ENCODERS); + igt_assert(data->res->count_crtcs <= MAX_CRTCS); + + for (i = 0; i < data->res->count_connectors; i++) { + data->connectors[i] = drmModeGetConnector(drm_fd, + data->res->connectors[i]); + data->edids[i] = get_connector_edid(data->connectors[i], i); + } + for (i = 0; i < data->res->count_encoders; i++) + data->encoders[i] = drmModeGetEncoder(drm_fd, + data->res->encoders[i]); + for (i = 0; i < data->res->count_crtcs; i++) + data->crtcs[i] = drmModeGetCrtc(drm_fd, data->res->crtcs[i]); +} + +static void free_drm_info(struct compare_data *data) +{ + int i; + + for (i = 0; i < data->res->count_connectors; i++) { + drmModeFreeConnector(data->connectors[i]); + drmModeFreePropertyBlob(data->edids[i]); + } + for (i = 0; i < data->res->count_encoders; i++) + drmModeFreeEncoder(data->encoders[i]); + for (i = 0; i < data->res->count_crtcs; i++) + drmModeFreeCrtc(data->crtcs[i]); + + drmModeFreeResources(data->res); +} + +#define COMPARE(d1, d2, data) igt_assert(d1->data == d2->data) +#define COMPARE_ARRAY(d1, d2, size, data) do { \ + for (i = 0; i < size; i++) \ + igt_assert(d1->data[i] == d2->data[i]); \ +} while (0) + +static void assert_drm_resources_equal(struct compare_data *d1, + struct compare_data *d2) +{ + COMPARE(d1, d2, res->count_connectors); + COMPARE(d1, d2, res->count_encoders); + COMPARE(d1, d2, res->count_crtcs); + COMPARE(d1, d2, res->min_width); + COMPARE(d1, d2, res->max_width); + COMPARE(d1, d2, res->min_height); + COMPARE(d1, d2, res->max_height); +} + +static void assert_modes_equal(drmModeModeInfoPtr m1, drmModeModeInfoPtr m2) +{ + COMPARE(m1, m2, clock); + COMPARE(m1, m2, hdisplay); + COMPARE(m1, m2, hsync_start); + COMPARE(m1, m2, hsync_end); + COMPARE(m1, m2, htotal); + COMPARE(m1, m2, hskew); + COMPARE(m1, m2, vdisplay); + COMPARE(m1, m2, vsync_start); + COMPARE(m1, m2, vsync_end); + COMPARE(m1, m2, vtotal); + COMPARE(m1, m2, vscan); + COMPARE(m1, m2, vrefresh); + COMPARE(m1, m2, flags); + COMPARE(m1, m2, type); + igt_assert(strcmp(m1->name, m2->name) == 0); +} + +static void assert_drm_connectors_equal(drmModeConnectorPtr c1, + drmModeConnectorPtr c2) +{ + int i; + + COMPARE(c1, c2, connector_id); + COMPARE(c1, c2, connector_type); + COMPARE(c1, c2, connector_type_id); + COMPARE(c1, c2, mmWidth); + COMPARE(c1, c2, mmHeight); + COMPARE(c1, c2, count_modes); + COMPARE(c1, c2, count_props); + COMPARE(c1, c2, count_encoders); + COMPARE_ARRAY(c1, c2, c1->count_props, props); + COMPARE_ARRAY(c1, c2, c1->count_encoders, encoders); + + for (i = 0; i < c1->count_modes; i++) + assert_modes_equal(&c1->modes[0], &c2->modes[0]); +} + +static void assert_drm_encoders_equal(drmModeEncoderPtr e1, + drmModeEncoderPtr e2) +{ + COMPARE(e1, e2, encoder_id); + COMPARE(e1, e2, encoder_type); + COMPARE(e1, e2, possible_crtcs); + COMPARE(e1, e2, possible_clones); +} + +static void assert_drm_crtcs_equal(drmModeCrtcPtr c1, drmModeCrtcPtr c2) +{ + COMPARE(c1, c2, crtc_id); +} + +static void assert_drm_edids_equal(drmModePropertyBlobPtr e1, + drmModePropertyBlobPtr e2) +{ + if (!e1 && !e2) + return; + igt_assert(e1 && e2); + + COMPARE(e1, e2, id); + COMPARE(e1, e2, length); + + igt_assert(memcmp(e1->data, e2->data, e1->length) == 0); +} + +static void assert_drm_infos_equal(struct compare_data *d1, + struct compare_data *d2) +{ + int i; + + assert_drm_resources_equal(d1, d2); + + for (i = 0; i < d1->res->count_connectors; i++) { + assert_drm_connectors_equal(d1->connectors[i], + d2->connectors[i]); + assert_drm_edids_equal(d1->edids[i], d2->edids[i]); + } + + for (i = 0; i < d1->res->count_encoders; i++) + assert_drm_encoders_equal(d1->encoders[i], d2->encoders[i]); + + for (i = 0; i < d1->res->count_crtcs; i++) + assert_drm_crtcs_equal(d1->crtcs[i], d2->crtcs[i]); +} + +/* We could check the checksum too, but just the header is probably enough. */ +static bool edid_is_valid(const unsigned char *edid) +{ + char edid_header[] = { + 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0, + }; + + return (memcmp(edid, edid_header, sizeof(edid_header)) == 0); +} + +static int count_drm_valid_edids(struct mode_set_data *data) +{ + int i, ret = 0; + + for (i = 0; i < data->res->count_connectors; i++) + if (data->edids[i] && edid_is_valid(data->edids[i]->data)) + ret++; + return ret; +} + +static bool i2c_edid_is_valid(int fd) +{ + int rc; + unsigned char edid[128] = {}; + struct i2c_msg msgs[] = { + { /* Start at 0. */ + .addr = 0x50, + .flags = 0, + .len = 1, + .buf = edid, + }, { /* Now read the EDID. */ + .addr = 0x50, + .flags = I2C_M_RD, + .len = 128, + .buf = edid, + } + }; + struct i2c_rdwr_ioctl_data msgset = { + .msgs = msgs, + .nmsgs = 2, + }; + + rc = ioctl(fd, I2C_RDWR, &msgset); + return (rc >= 0) ? edid_is_valid(edid) : false; +} + +static int count_i2c_valid_edids(void) +{ + int fd, ret = 0; + DIR *dir; + + struct dirent *dirent; + char full_name[32]; + + dir = opendir("/dev/"); + igt_assert(dir); + + while ((dirent = readdir(dir))) { + if (strncmp(dirent->d_name, "i2c-", 4) == 0) { + snprintf(full_name, 32, "/dev/%s", dirent->d_name); + fd = open(full_name, O_RDWR); + igt_assert(fd != -1); + if (i2c_edid_is_valid(fd)) + ret++; + close(fd); + } + } + + closedir(dir); + + return ret; +} + +static void test_i2c(struct mode_set_data *data) +{ + int i2c_edids = count_i2c_valid_edids(); + int drm_edids = count_drm_valid_edids(data); + + igt_assert_cmpint(i2c_edids, ==, drm_edids); +} + +static void setup_pc8(void) +{ + has_pc8 = false; + + /* Only Haswell supports the PC8 feature. */ + if (!IS_HASWELL(ms_data.devid) && !IS_BROADWELL(ms_data.devid)) + return; + + /* Make sure our Kernel supports MSR and the module is loaded. */ + igt_assert(system("modprobe -q msr > /dev/null 2>&1") != -1); + + msr_fd = open("/dev/cpu/0/msr", O_RDONLY); + igt_assert_f(msr_fd >= 0, + "Can't open /dev/cpu/0/msr.\n"); + + /* Non-ULT machines don't support PC8+. */ + if (!supports_pc8_plus_residencies()) + return; + + pc8_status_fd = open("/sys/kernel/debug/dri/0/i915_pc8_status", + O_RDONLY); + igt_assert_f(pc8_status_fd >= 0, + "Can't open /sys/kernel/debug/dri/0/i915_pc8_status"); + + has_pc8 = true; +} + +/* If we want to actually reach PC8+ states, we need to properly configure all + * the devices on the system to allow this. This function will try to setup the + * things we know we need, but won't scream in case anything fails: we don't + * know which devices are present on your machine, so we can't really expect + * anything, just try to help with the more common problems. */ +static void setup_non_graphics_runtime_pm(void) +{ + int fd, i; + char *file_name; + + /* Disk runtime PM policies. */ + file_name = malloc(PATH_MAX); + for (i = 0; ; i++) { + + snprintf(file_name, PATH_MAX, + "/sys/class/scsi_host/host%d/link_power_management_policy", + i); + + fd = open(file_name, O_WRONLY); + if (fd < 0) + break; + + write(fd, "min_power\n", 10); + close(fd); + } + free(file_name); + + /* Audio runtime PM policies. */ + fd = open("/sys/module/snd_hda_intel/parameters/power_save", O_WRONLY); + if (fd >= 0) { + write(fd, "1\n", 2); + close(fd); + } + fd = open("/sys/bus/pci/devices/0000:00:03.0/power/control", O_WRONLY); + if (fd >= 0) { + write(fd, "auto\n", 5); + close(fd); + } +} + +static void setup_environment(void) +{ + drm_fd = drm_open_any(); + igt_assert(drm_fd >= 0); + + igt_require_f(drmSetMaster(drm_fd) == 0, "Can't become DRM master, " + "please check if no other DRM client is running.\n"); + + init_mode_set_data(&ms_data); + + setup_non_graphics_runtime_pm(); + + has_runtime_pm = igt_setup_runtime_pm(); + setup_pc8(); + + igt_info("Runtime PM support: %d\n", has_runtime_pm); + igt_info("PC8 residency support: %d\n", has_pc8); + + igt_require(has_runtime_pm); +} + +static void teardown_environment(void) +{ + struct scanout_fb *fb, *fb_next; + + fb = fbs; + while (fb) { + fb_next = fb->next; + free(fb); + fb = fb_next; + } + + fini_mode_set_data(&ms_data); + drmClose(drm_fd); + close(msr_fd); + if (has_pc8) + close(pc8_status_fd); +} + +static void basic_subtest(void) +{ + disable_all_screens(&ms_data); + igt_assert(wait_for_suspended()); + + enable_one_screen(&ms_data); + igt_assert(wait_for_active()); +} + +static void pc8_residency_subtest(void) +{ + igt_require(has_pc8); + + /* Make sure PC8+ residencies move! */ + disable_all_screens(&ms_data); + igt_assert_f(pc8_plus_residency_changed(120), + "Machine is not reaching PC8+ states, please check its " + "configuration.\n"); + + /* Make sure PC8+ residencies stop! */ + enable_one_screen(&ms_data); + igt_assert_f(!pc8_plus_residency_changed(10), + "PC8+ residency didn't stop with screen enabled.\n"); +} + +static void modeset_subtest(enum screen_type type, int rounds, int wait_flags) +{ + int i; + + if (wait_flags & WAIT_PC8_RES) + igt_require(has_pc8); + + for (i = 0; i < rounds; i++) { + if (wait_flags & USE_DPMS) + disable_all_screens_dpms(&ms_data); + else + disable_all_screens(&ms_data); + + if (wait_flags & WAIT_STATUS) + igt_assert(wait_for_suspended()); + if (wait_flags & WAIT_PC8_RES) + igt_assert(pc8_plus_residency_changed(120)); + if (wait_flags & WAIT_EXTRA) + sleep(5); + + /* If we skip this line it's because the type of screen we want + * is not connected. */ + igt_require(enable_one_screen_with_type(&ms_data, type)); + if (wait_flags & WAIT_STATUS) + igt_assert(wait_for_active()); + if (wait_flags & WAIT_PC8_RES) + igt_assert(!pc8_plus_residency_changed(5)); + if (wait_flags & WAIT_EXTRA) + sleep(5); + } +} + +/* Test of the DRM resources reported by the IOCTLs are still the same. This + * ensures we still see the monitors with the same eyes. We get the EDIDs and + * compare them, which ensures we use DP AUX or GMBUS depending on what's + * connected. */ +static void drm_resources_equal_subtest(void) +{ + struct compare_data pre_suspend, during_suspend, post_suspend; + + enable_one_screen(&ms_data); + igt_assert(wait_for_active()); + get_drm_info(&pre_suspend); + igt_assert(wait_for_active()); + + disable_all_screens(&ms_data); + igt_assert(wait_for_suspended()); + get_drm_info(&during_suspend); + igt_assert(wait_for_suspended()); + + enable_one_screen(&ms_data); + igt_assert(wait_for_active()); + get_drm_info(&post_suspend); + igt_assert(wait_for_active()); + + assert_drm_infos_equal(&pre_suspend, &during_suspend); + assert_drm_infos_equal(&pre_suspend, &post_suspend); + + free_drm_info(&pre_suspend); + free_drm_info(&during_suspend); + free_drm_info(&post_suspend); +} + +static void i2c_subtest_check_environment(void) +{ + int i2c_dev_files = 0; + DIR *dev_dir; + struct dirent *dirent; + + /* Make sure the /dev/i2c-* files exist. */ + igt_assert(system("modprobe -q i2c-dev > /dev/null 2>&1") != -1); + + dev_dir = opendir("/dev"); + igt_assert(dev_dir); + while ((dirent = readdir(dev_dir))) { + if (strncmp(dirent->d_name, "i2c-", 4) == 0) + i2c_dev_files++; + } + closedir(dev_dir); + igt_require(i2c_dev_files); +} + +/* Try to use raw I2C, which also needs interrupts. */ +static void i2c_subtest(void) +{ + i2c_subtest_check_environment(); + + enable_one_screen(&ms_data); + igt_assert(wait_for_active()); + + disable_all_screens(&ms_data); + igt_assert(wait_for_suspended()); + test_i2c(&ms_data); + igt_assert(wait_for_suspended()); + + enable_one_screen(&ms_data); +} + +static void read_full_file(const char *name) +{ + int rc, fd; + char buf[128]; + + igt_assert_f(wait_for_suspended(), "File: %s\n", name); + + fd = open(name, O_RDONLY); + if (fd < 0) + return; + + do { + rc = read(fd, buf, ARRAY_SIZE(buf)); + } while (rc == ARRAY_SIZE(buf)); + + rc = close(fd); + igt_assert(rc == 0); + + igt_assert_f(wait_for_suspended(), "File: %s\n", name); +} + +static void read_files_from_dir(const char *name, int level) +{ + DIR *dir; + struct dirent *dirent; + char *full_name; + int rc; + + dir = opendir(name); + igt_assert(dir); + + full_name = malloc(PATH_MAX); + + igt_assert(level < 128); + + while ((dirent = readdir(dir))) { + struct stat stat_buf; + + if (strcmp(dirent->d_name, ".") == 0) + continue; + if (strcmp(dirent->d_name, "..") == 0) + continue; + + snprintf(full_name, PATH_MAX, "%s/%s", name, dirent->d_name); + + rc = lstat(full_name, &stat_buf); + igt_assert(rc == 0); + + if (S_ISDIR(stat_buf.st_mode)) + read_files_from_dir(full_name, level + 1); + + if (S_ISREG(stat_buf.st_mode)) + read_full_file(full_name); + } + + free(full_name); + closedir(dir); +} + +/* This test will probably pass, with a small chance of hanging the machine in + * case of bugs. Many of the bugs exercised by this patch just result in dmesg + * errors, so a "pass" here should be confirmed by a check on dmesg. */ +static void debugfs_read_subtest(void) +{ + const char *path = "/sys/kernel/debug/dri/0"; + DIR *dir; + + dir = opendir(path); + igt_require_f(dir, "Can't open the debugfs directory\n"); + closedir(dir); + + disable_all_screens(&ms_data); + igt_assert(wait_for_suspended()); + + read_files_from_dir(path, 0); +} + +/* Read the comment on debugfs_read_subtest(). */ +static void sysfs_read_subtest(void) +{ + const char *path = "/sys/devices/pci0000:00/0000:00:02.0"; + DIR *dir; + + dir = opendir(path); + igt_require_f(dir, "Can't open the sysfs directory\n"); + closedir(dir); + + disable_all_screens(&ms_data); + igt_assert(wait_for_suspended()); + + read_files_from_dir(path, 0); +} + +/* Make sure we don't suspend when we have the i915_forcewake_user file open. */ +static void debugfs_forcewake_user_subtest(void) +{ + int fd, rc; + + igt_require(intel_gen(ms_data.devid) >= 6); + + disable_all_screens(&ms_data); + igt_assert(wait_for_suspended()); + + fd = igt_open_forcewake_handle(); + igt_require(fd >= 0); + + if (has_runtime_pm) { + igt_assert(wait_for_active()); + sleep(10); + igt_assert(wait_for_active()); + } else { + igt_assert(wait_for_suspended()); + } + + rc = close(fd); + igt_assert(rc == 0); + + igt_assert(wait_for_suspended()); +} + +static void gem_mmap_subtest(bool gtt_mmap) +{ + int i; + uint32_t handle; + int buf_size = 8192; + uint8_t *gem_buf; + + /* Create, map and set data while the device is active. */ + enable_one_screen(&ms_data); + igt_assert(wait_for_active()); + + handle = gem_create(drm_fd, buf_size); + + if (gtt_mmap) + gem_buf = gem_mmap__gtt(drm_fd, handle, buf_size, + PROT_READ | PROT_WRITE); + else + gem_buf = gem_mmap__cpu(drm_fd, handle, buf_size, 0); + + + for (i = 0; i < buf_size; i++) + gem_buf[i] = i & 0xFF; + + for (i = 0; i < buf_size; i++) + igt_assert(gem_buf[i] == (i & 0xFF)); + + /* Now suspend, read and modify. */ + disable_all_screens(&ms_data); + igt_assert(wait_for_suspended()); + + for (i = 0; i < buf_size; i++) + igt_assert(gem_buf[i] == (i & 0xFF)); + igt_assert(wait_for_suspended()); + + for (i = 0; i < buf_size; i++) + gem_buf[i] = (~i & 0xFF); + igt_assert(wait_for_suspended()); + + /* Now resume and see if it's still there. */ + enable_one_screen(&ms_data); + igt_assert(wait_for_active()); + for (i = 0; i < buf_size; i++) + igt_assert(gem_buf[i] == (~i & 0xFF)); + + igt_assert(munmap(gem_buf, buf_size) == 0); + + /* Now the opposite: suspend, and try to create the mmap while + * suspended. */ + disable_all_screens(&ms_data); + igt_assert(wait_for_suspended()); + + if (gtt_mmap) + gem_buf = gem_mmap__gtt(drm_fd, handle, buf_size, + PROT_READ | PROT_WRITE); + else + gem_buf = gem_mmap__cpu(drm_fd, handle, buf_size, 0); + + igt_assert(wait_for_suspended()); + + for (i = 0; i < buf_size; i++) + gem_buf[i] = i & 0xFF; + + for (i = 0; i < buf_size; i++) + igt_assert(gem_buf[i] == (i & 0xFF)); + + igt_assert(wait_for_suspended()); + + /* Resume and check if it's still there. */ + enable_one_screen(&ms_data); + igt_assert(wait_for_active()); + for (i = 0; i < buf_size; i++) + igt_assert(gem_buf[i] == (i & 0xFF)); + + igt_assert(munmap(gem_buf, buf_size) == 0); + gem_close(drm_fd, handle); +} + +static void gem_pread_subtest(void) +{ + int i; + uint32_t handle; + int buf_size = 8192; + uint8_t *cpu_buf, *read_buf; + + cpu_buf = malloc(buf_size); + read_buf = malloc(buf_size); + igt_assert(cpu_buf); + igt_assert(read_buf); + memset(cpu_buf, 0, buf_size); + memset(read_buf, 0, buf_size); + + /* Create and set data while the device is active. */ + enable_one_screen(&ms_data); + igt_assert(wait_for_active()); + + handle = gem_create(drm_fd, buf_size); + + for (i = 0; i < buf_size; i++) + cpu_buf[i] = i & 0xFF; + + gem_write(drm_fd, handle, 0, cpu_buf, buf_size); + + gem_read(drm_fd, handle, 0, read_buf, buf_size); + + for (i = 0; i < buf_size; i++) + igt_assert(cpu_buf[i] == read_buf[i]); + + /* Now suspend, read and modify. */ + disable_all_screens(&ms_data); + igt_assert(wait_for_suspended()); + + memset(read_buf, 0, buf_size); + gem_read(drm_fd, handle, 0, read_buf, buf_size); + + for (i = 0; i < buf_size; i++) + igt_assert(cpu_buf[i] == read_buf[i]); + igt_assert(wait_for_suspended()); + + for (i = 0; i < buf_size; i++) + cpu_buf[i] = (~i & 0xFF); + gem_write(drm_fd, handle, 0, cpu_buf, buf_size); + igt_assert(wait_for_suspended()); + + /* Now resume and see if it's still there. */ + enable_one_screen(&ms_data); + igt_assert(wait_for_active()); + + memset(read_buf, 0, buf_size); + gem_read(drm_fd, handle, 0, read_buf, buf_size); + + for (i = 0; i < buf_size; i++) + igt_assert(cpu_buf[i] == read_buf[i]); + + gem_close(drm_fd, handle); + + free(cpu_buf); + free(read_buf); +} + +/* Paints a square of color $color, size $width x $height, at position $x x $y + * of $dst_handle, which contains pitch $pitch. */ +static void submit_blt_cmd(uint32_t dst_handle, uint16_t x, uint16_t y, + uint16_t width, uint16_t height, uint32_t pitch, + uint32_t color, uint32_t *presumed_dst_offset) +{ + int i, reloc_pos; + uint32_t batch_handle; + int batch_size = 8 * sizeof(uint32_t); + uint32_t batch_buf[batch_size]; + struct drm_i915_gem_execbuffer2 execbuf = {}; + struct drm_i915_gem_exec_object2 objs[2] = {{}, {}}; + struct drm_i915_gem_relocation_entry relocs[1] = {{}}; + struct drm_i915_gem_wait gem_wait; + + i = 0; + + if (intel_gen(ms_data.devid) >= 8) + batch_buf[i++] = XY_COLOR_BLT_CMD_NOLEN | + XY_COLOR_BLT_WRITE_ALPHA | + XY_COLOR_BLT_WRITE_RGB | 0x5; + else + batch_buf[i++] = XY_COLOR_BLT_CMD_NOLEN | + XY_COLOR_BLT_WRITE_ALPHA | + XY_COLOR_BLT_WRITE_RGB | 0x4; + batch_buf[i++] = (3 << 24) | (0xF0 << 16) | (pitch); + batch_buf[i++] = (y << 16) | x; + batch_buf[i++] = ((y + height) << 16) | (x + width); + reloc_pos = i; + batch_buf[i++] = *presumed_dst_offset; + if (intel_gen(ms_data.devid) >= 8) + batch_buf[i++] = 0; + batch_buf[i++] = color; + + batch_buf[i++] = MI_BATCH_BUFFER_END; + if (intel_gen(ms_data.devid) < 8) + batch_buf[i++] = MI_NOOP; + + igt_assert(i * sizeof(uint32_t) == batch_size); + + batch_handle = gem_create(drm_fd, batch_size); + gem_write(drm_fd, batch_handle, 0, batch_buf, batch_size); + + relocs[0].target_handle = dst_handle; + relocs[0].delta = 0; + relocs[0].offset = reloc_pos * sizeof(uint32_t); + relocs[0].presumed_offset = *presumed_dst_offset; + relocs[0].read_domains = 0; + relocs[0].write_domain = I915_GEM_DOMAIN_RENDER; + + objs[0].handle = dst_handle; + objs[0].alignment = 64; + + objs[1].handle = batch_handle; + objs[1].relocation_count = 1; + objs[1].relocs_ptr = (uintptr_t)relocs; + + execbuf.buffers_ptr = (uintptr_t)objs; + execbuf.buffer_count = 2; + execbuf.batch_len = batch_size; + execbuf.flags = I915_EXEC_BLT; + i915_execbuffer2_set_context_id(execbuf, 0); + + do_ioctl(drm_fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + + *presumed_dst_offset = relocs[0].presumed_offset; + + gem_wait.flags = 0; + gem_wait.timeout_ns = 10000000000LL; /* 10s */ + + gem_wait.bo_handle = batch_handle; + do_ioctl(drm_fd, DRM_IOCTL_I915_GEM_WAIT, &gem_wait); + + gem_wait.bo_handle = dst_handle; + do_ioctl(drm_fd, DRM_IOCTL_I915_GEM_WAIT, &gem_wait); + + gem_close(drm_fd, batch_handle); +} + +/* Make sure we can submit a batch buffer and verify its result. */ +static void gem_execbuf_subtest(void) +{ + int x, y; + uint32_t handle; + int bpp = 4; + int pitch = 128 * bpp; + int dst_size = 128 * 128 * bpp; /* 128x128 square */ + uint32_t *cpu_buf; + uint32_t presumed_offset = 0; + int sq_x = 5, sq_y = 10, sq_w = 15, sq_h = 20; + uint32_t color; + + /* Create and set data while the device is active. */ + enable_one_screen(&ms_data); + igt_assert(wait_for_active()); + + handle = gem_create(drm_fd, dst_size); + + cpu_buf = malloc(dst_size); + igt_assert(cpu_buf); + memset(cpu_buf, 0, dst_size); + gem_write(drm_fd, handle, 0, cpu_buf, dst_size); + + /* Now suspend and try it. */ + disable_all_screens(&ms_data); + igt_assert(wait_for_suspended()); + + color = 0x12345678; + submit_blt_cmd(handle, sq_x, sq_y, sq_w, sq_h, pitch, color, + &presumed_offset); + igt_assert(wait_for_suspended()); + + gem_read(drm_fd, handle, 0, cpu_buf, dst_size); + igt_assert(wait_for_suspended()); + for (y = 0; y < 128; y++) { + for (x = 0; x < 128; x++) { + uint32_t px = cpu_buf[y * 128 + x]; + + if (y >= sq_y && y < (sq_y + sq_h) && + x >= sq_x && x < (sq_x + sq_w)) + igt_assert(px == color); + else + igt_assert(px == 0); + } + } + + /* Now resume and check for it again. */ + enable_one_screen(&ms_data); + igt_assert(wait_for_active()); + + memset(cpu_buf, 0, dst_size); + gem_read(drm_fd, handle, 0, cpu_buf, dst_size); + for (y = 0; y < 128; y++) { + for (x = 0; x < 128; x++) { + uint32_t px = cpu_buf[y * 128 + x]; + + if (y >= sq_y && y < (sq_y + sq_h) && + x >= sq_x && x < (sq_x + sq_w)) + igt_assert(px == color); + else + igt_assert(px == 0); + } + } + + /* Now we'll do the opposite: do the blt while active, then read while + * suspended. We use the same spot, but a different color. As a bonus, + * we're testing the presumed_offset from the previous command. */ + color = 0x87654321; + submit_blt_cmd(handle, sq_x, sq_y, sq_w, sq_h, pitch, color, + &presumed_offset); + + disable_all_screens(&ms_data); + igt_assert(wait_for_suspended()); + + memset(cpu_buf, 0, dst_size); + gem_read(drm_fd, handle, 0, cpu_buf, dst_size); + for (y = 0; y < 128; y++) { + for (x = 0; x < 128; x++) { + uint32_t px = cpu_buf[y * 128 + x]; + + if (y >= sq_y && y < (sq_y + sq_h) && + x >= sq_x && x < (sq_x + sq_w)) + igt_assert(px == color); + else + igt_assert(px == 0); + } + } + + gem_close(drm_fd, handle); + + free(cpu_buf); +} + +/* Assuming execbuf already works, let's see what happens when we force many + * suspend/resume cycles with commands. */ +static void gem_execbuf_stress_subtest(int rounds, int wait_flags) +{ + int i; + int batch_size = 4 * sizeof(uint32_t); + uint32_t batch_buf[batch_size]; + uint32_t handle; + struct drm_i915_gem_execbuffer2 execbuf = {}; + struct drm_i915_gem_exec_object2 objs[1] = {{}}; + + if (wait_flags & WAIT_PC8_RES) + igt_require(has_pc8); + + i = 0; + batch_buf[i++] = MI_NOOP; + batch_buf[i++] = MI_NOOP; + batch_buf[i++] = MI_BATCH_BUFFER_END; + batch_buf[i++] = MI_NOOP; + igt_assert(i * sizeof(uint32_t) == batch_size); + + disable_all_screens(&ms_data); + igt_assert(wait_for_suspended()); + + handle = gem_create(drm_fd, batch_size); + gem_write(drm_fd, handle, 0, batch_buf, batch_size); + + objs[0].handle = handle; + + execbuf.buffers_ptr = (uintptr_t)objs; + execbuf.buffer_count = 1; + execbuf.batch_len = batch_size; + execbuf.flags = I915_EXEC_RENDER; + i915_execbuffer2_set_context_id(execbuf, 0); + + for (i = 0; i < rounds; i++) { + do_ioctl(drm_fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + + if (wait_flags & WAIT_STATUS) + igt_assert(wait_for_suspended()); + if (wait_flags & WAIT_PC8_RES) + igt_assert(pc8_plus_residency_changed(120)); + if (wait_flags & WAIT_EXTRA) + sleep(5); + } + + gem_close(drm_fd, handle); +} + +/* When this test was written, it triggered WARNs and DRM_ERRORs on dmesg. */ +static void gem_idle_subtest(void) +{ + disable_all_screens(&ms_data); + igt_assert(wait_for_suspended()); + + sleep(5); + + gem_quiescent_gpu(drm_fd); +} + +/* This also triggered WARNs on dmesg at some point. */ +static void reg_read_ioctl_subtest(void) +{ + struct drm_i915_reg_read rr = { + .offset = 0x2358, /* render ring timestamp */ + }; + + disable_all_screens(&ms_data); + igt_assert(wait_for_suspended()); + + do_ioctl(drm_fd, DRM_IOCTL_I915_REG_READ, &rr); + + igt_assert(wait_for_suspended()); +} + +static bool device_in_pci_d3(void) +{ + struct pci_device *pci_dev; + int rc; + uint16_t val; + + pci_dev = intel_get_pci_device(); + + rc = pci_device_cfg_read_u16(pci_dev, &val, 0xd4); + igt_assert(rc == 0); + + return (val & 0x3) == 0x3; +} + +static void pci_d3_state_subtest(void) +{ + igt_require(has_runtime_pm); + + disable_all_screens(&ms_data); + igt_assert(wait_for_suspended()); + + igt_assert(device_in_pci_d3()); + + enable_one_screen(&ms_data); + igt_assert(wait_for_active()); + + igt_assert(!device_in_pci_d3()); +} + +static void stay_subtest(void) +{ + disable_all_screens(&ms_data); + igt_assert(wait_for_suspended()); + + while (1) + sleep(600); +} + +static void system_suspend_subtest(void) +{ + disable_all_screens(&ms_data); + igt_assert(wait_for_suspended()); + igt_system_suspend_autoresume(); + igt_assert(wait_for_suspended()); +} + +int main(int argc, char *argv[]) +{ + int rounds = 50; + bool stay = false; + + igt_subtest_init(argc, argv); + + /* The --quick option makes the stress tests not so stressful. Useful + * when you're developing and just want to make a quick test to make + * sure you didn't break everything. */ + if (argc > 1 && strcmp(argv[1], "--quick") == 0) + rounds = 10; + + /* The --stay option enables a mode where we disable all the screens, + * then stay like that, runtime suspended. This mode is useful for + * running manual tests while debugging. */ + if (argc > 1 && strcmp(argv[1], "--stay") == 0) + stay = true; + + /* Skip instead of failing in case the machine is not prepared to reach + * PC8+. We don't want bug reports from cases where the machine is just + * not properly configured. */ + igt_fixture + setup_environment(); + + if (stay) + igt_subtest("stay") + stay_subtest(); + + /* Essential things */ + igt_subtest("rte") + basic_subtest(); + igt_subtest("drm-resources-equal") + drm_resources_equal_subtest(); + igt_subtest("pci-d3-state") + pci_d3_state_subtest(); + + /* Basic modeset */ + igt_subtest("modeset-lpsp") + modeset_subtest(SCREEN_TYPE_LPSP, 1, WAIT_STATUS); + igt_subtest("modeset-non-lpsp") + modeset_subtest(SCREEN_TYPE_NON_LPSP, 1, WAIT_STATUS); + igt_subtest("dpms-lpsp") + modeset_subtest(SCREEN_TYPE_LPSP, 1, WAIT_STATUS | USE_DPMS); + igt_subtest("dpms-non-lpsp") + modeset_subtest(SCREEN_TYPE_NON_LPSP, 1, WAIT_STATUS | USE_DPMS); + + /* GEM */ + igt_subtest("gem-mmap-cpu") + gem_mmap_subtest(false); + igt_subtest("gem-mmap-gtt") + gem_mmap_subtest(true); + igt_subtest("gem-pread") + gem_pread_subtest(); + igt_subtest("gem-execbuf") + gem_execbuf_subtest(); + igt_subtest("gem-idle") + gem_idle_subtest(); + + /* Misc */ + igt_subtest("reg-read-ioctl") + reg_read_ioctl_subtest(); + igt_subtest("i2c") + i2c_subtest(); + igt_subtest("pc8-residency") + pc8_residency_subtest(); + igt_subtest("debugfs-read") + debugfs_read_subtest(); + igt_subtest("debugfs-forcewake-user") + debugfs_forcewake_user_subtest(); + igt_subtest("sysfs-read") + sysfs_read_subtest(); + + /* Modeset stress */ + igt_subtest("modeset-lpsp-stress") + modeset_subtest(SCREEN_TYPE_LPSP, rounds, WAIT_STATUS); + igt_subtest("modeset-non-lpsp-stress") + modeset_subtest(SCREEN_TYPE_NON_LPSP, rounds, WAIT_STATUS); + igt_subtest("modeset-lpsp-stress-no-wait") + modeset_subtest(SCREEN_TYPE_LPSP, rounds, DONT_WAIT); + igt_subtest("modeset-non-lpsp-stress-no-wait") + modeset_subtest(SCREEN_TYPE_NON_LPSP, rounds, DONT_WAIT); + igt_subtest("modeset-pc8-residency-stress") + modeset_subtest(SCREEN_TYPE_ANY, rounds, WAIT_PC8_RES); + igt_subtest("modeset-stress-extra-wait") + modeset_subtest(SCREEN_TYPE_ANY, rounds, + WAIT_STATUS | WAIT_EXTRA); + + /* System suspend */ + igt_subtest("system-suspend") + system_suspend_subtest(); + + /* GEM stress */ + igt_subtest("gem-execbuf-stress") + gem_execbuf_stress_subtest(rounds, WAIT_STATUS); + igt_subtest("gem-execbuf-stress-pc8") + gem_execbuf_stress_subtest(rounds, WAIT_PC8_RES); + igt_subtest("gem-execbuf-stress-extra-wait") + gem_execbuf_stress_subtest(rounds, WAIT_STATUS | WAIT_EXTRA); + + igt_fixture + teardown_environment(); + + igt_exit(); +} diff --git a/tests/pm_rps.c b/tests/pm_rps.c new file mode 100644 index 00000000..c1156a5f --- /dev/null +++ b/tests/pm_rps.c @@ -0,0 +1,595 @@ +/* + * Copyright © 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Ben Widawsky <ben@bwidawsk.net> + * Jeff McGee <jeff.mcgee@intel.com> + * + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <getopt.h> +#include <fcntl.h> +#include <signal.h> +#include <errno.h> + +#include "drmtest.h" +#include "intel_io.h" +#include "intel_bufmgr.h" +#include "intel_batchbuffer.h" +#include "intel_chipset.h" +#include "igt_debugfs.h" +#include "ioctl_wrappers.h" + +static int drm_fd; + +static const char sysfs_base_path[] = "/sys/class/drm/card%d/gt_%s_freq_mhz"; +enum { + CUR, + MIN, + MAX, + RP0, + RP1, + RPn, + NUMFREQ +}; + +static int origfreqs[NUMFREQ]; + +struct junk { + const char *name; + const char *mode; + FILE *filp; +} stuff[] = { + { "cur", "r", NULL }, { "min", "rb+", NULL }, { "max", "rb+", NULL }, { "RP0", "r", NULL }, { "RP1", "r", NULL }, { "RPn", "r", NULL }, { NULL, NULL, NULL } +}; + +static int readval(FILE *filp) +{ + int val; + int scanned; + + rewind(filp); + scanned = fscanf(filp, "%d", &val); + igt_assert(scanned == 1); + + return val; +} + +static void read_freqs(int *freqs) +{ + int i; + + for (i = 0; i < NUMFREQ; i++) + freqs[i] = readval(stuff[i].filp); +} + +static int do_writeval(FILE *filp, int val, int lerrno) +{ + int ret, orig; + + orig = readval(filp); + rewind(filp); + ret = fprintf(filp, "%d", val); + + if (lerrno) { + /* Expecting specific error */ + igt_assert(ret == EOF && errno == lerrno); + igt_assert(readval(filp) == orig); + } else { + /* Expecting no error */ + igt_assert(ret != EOF); + igt_assert(readval(filp) == val); + } + + return ret; +} +#define writeval(filp, val) do_writeval(filp, val, 0) +#define writeval_inval(filp, val) do_writeval(filp, val, EINVAL) + +static void checkit(const int *freqs) +{ + igt_assert_cmpint(freqs[MIN], <=, freqs[MAX]); + igt_assert_cmpint(freqs[CUR], <=, freqs[MAX]); + igt_assert_cmpint(freqs[MIN], <=, freqs[CUR]); + igt_assert_cmpint(freqs[RPn], <=, freqs[MIN]); + igt_assert_cmpint(freqs[MAX], <=, freqs[RP0]); + igt_assert_cmpint(freqs[RP1], <=, freqs[RP0]); + igt_assert_cmpint(freqs[RPn], <=, freqs[RP1]); + igt_assert(freqs[RP0] != 0); + igt_assert(freqs[RP1] != 0); +} + +static void matchit(const int *freqs1, const int *freqs2) +{ + igt_assert_cmpint(freqs1[CUR], ==, freqs2[CUR]); + igt_assert_cmpint(freqs1[MIN], ==, freqs2[MIN]); + igt_assert_cmpint(freqs1[MAX], ==, freqs2[MAX]); + igt_assert_cmpint(freqs1[RP0], ==, freqs2[RP0]); + igt_assert_cmpint(freqs1[RP1], ==, freqs2[RP1]); + igt_assert_cmpint(freqs1[RPn], ==, freqs2[RPn]); +} + +static void dump(const int *freqs) +{ + int i; + + igt_debug("gt freq (MHz):"); + for (i = 0; i < NUMFREQ; i++) + igt_debug(" %s=%d", stuff[i].name, freqs[i]); + + igt_debug("\n"); +} + +enum load { + LOW, + HIGH +}; + +static struct load_helper { + int devid; + int has_ppgtt; + drm_intel_bufmgr *bufmgr; + struct intel_batchbuffer *batch; + drm_intel_bo *target_buffer; + enum load load; + bool exit; + struct igt_helper_process igt_proc; + drm_intel_bo *src, *dst; +} lh; + +static void load_helper_signal_handler(int sig) +{ + if (sig == SIGUSR2) + lh.load = lh.load == LOW ? HIGH : LOW; + else + lh.exit = true; +} + +static void emit_store_dword_imm(uint32_t val) +{ + int cmd; + struct intel_batchbuffer *batch = lh.batch; + + cmd = MI_STORE_DWORD_IMM; + if (!lh.has_ppgtt) + cmd |= MI_MEM_VIRTUAL; + + if (intel_gen(lh.devid) >= 8) { + BEGIN_BATCH(4); + OUT_BATCH(cmd); + OUT_RELOC(lh.target_buffer, I915_GEM_DOMAIN_INSTRUCTION, + I915_GEM_DOMAIN_INSTRUCTION, 0); + OUT_BATCH(0); + OUT_BATCH(val); + ADVANCE_BATCH(); + } else { + BEGIN_BATCH(4); + OUT_BATCH(cmd); + OUT_BATCH(0); /* reserved */ + OUT_RELOC(lh.target_buffer, I915_GEM_DOMAIN_INSTRUCTION, + I915_GEM_DOMAIN_INSTRUCTION, 0); + OUT_BATCH(val); + ADVANCE_BATCH(); + } +} + +#define LOAD_HELPER_PAUSE_USEC 500 +#define LOAD_HELPER_BO_SIZE (16*1024*1024) +static void load_helper_set_load(enum load load) +{ + igt_assert(lh.igt_proc.running); + + if (lh.load == load) + return; + + lh.load = load; + kill(lh.igt_proc.pid, SIGUSR2); +} + +static void load_helper_run(enum load load) +{ + /* + * FIXME fork helpers won't get cleaned up when started from within a + * subtest, so handle the case where it sticks around a bit too long. + */ + if (lh.igt_proc.running) { + load_helper_set_load(load); + return; + } + + lh.load = load; + + igt_fork_helper(&lh.igt_proc) { + uint32_t val = 0; + + signal(SIGUSR1, load_helper_signal_handler); + signal(SIGUSR2, load_helper_signal_handler); + + while (!lh.exit) { + if (lh.load == HIGH) + intel_copy_bo(lh.batch, lh.dst, lh.src, + LOAD_HELPER_BO_SIZE); + + emit_store_dword_imm(val); + intel_batchbuffer_flush_on_ring(lh.batch, 0); + val++; + + /* Lower the load by pausing after every submitted + * write. */ + if (lh.load == LOW) + usleep(LOAD_HELPER_PAUSE_USEC); + } + + /* Map buffer to stall for write completion */ + drm_intel_bo_map(lh.target_buffer, 0); + drm_intel_bo_unmap(lh.target_buffer); + + igt_debug("load helper sent %u dword writes\n", val); + } +} + +static void load_helper_stop(void) +{ + kill(lh.igt_proc.pid, SIGUSR1); + igt_wait_helper(&lh.igt_proc); +} + +static void load_helper_init(void) +{ + lh.devid = intel_get_drm_devid(drm_fd); + lh.has_ppgtt = gem_uses_aliasing_ppgtt(drm_fd); + + /* MI_STORE_DATA can only use GTT address on gen4+/g33 and needs + * snoopable mem on pre-gen6. Hence load-helper only works on gen6+, but + * that's also all we care about for the rps testcase*/ + igt_assert(intel_gen(lh.devid) >= 6); + lh.bufmgr = drm_intel_bufmgr_gem_init(drm_fd, 4096); + igt_assert(lh.bufmgr); + + drm_intel_bufmgr_gem_enable_reuse(lh.bufmgr); + + lh.batch = intel_batchbuffer_alloc(lh.bufmgr, lh.devid); + igt_assert(lh.batch); + + lh.target_buffer = drm_intel_bo_alloc(lh.bufmgr, "target bo", + 4096, 4096); + igt_assert(lh.target_buffer); + + lh.dst = drm_intel_bo_alloc(lh.bufmgr, "dst bo", + LOAD_HELPER_BO_SIZE, 4096); + igt_assert(lh.dst); + lh.src = drm_intel_bo_alloc(lh.bufmgr, "src bo", + LOAD_HELPER_BO_SIZE, 4096); + igt_assert(lh.src); +} + +static void load_helper_deinit(void) +{ + if (lh.igt_proc.running) + load_helper_stop(); + + if (lh.target_buffer) + drm_intel_bo_unreference(lh.target_buffer); + if (lh.src) + drm_intel_bo_unreference(lh.src); + if (lh.dst) + drm_intel_bo_unreference(lh.dst); + + if (lh.batch) + intel_batchbuffer_free(lh.batch); + + if (lh.bufmgr) + drm_intel_bufmgr_destroy(lh.bufmgr); +} + +static void min_max_config(void (*check)(void)) +{ + int fmid = (origfreqs[RPn] + origfreqs[RP0]) / 2; + + /* hw (and so kernel) currently rounds to 50 MHz ... */ + fmid = fmid / 50 * 50; + + igt_debug("\nCheck original min and max...\n"); + check(); + + igt_debug("\nSet min=RPn and max=RP0...\n"); + writeval(stuff[MIN].filp, origfreqs[RPn]); + writeval(stuff[MAX].filp, origfreqs[RP0]); + check(); + + igt_debug("\nIncrease min to midpoint...\n"); + writeval(stuff[MIN].filp, fmid); + check(); + + igt_debug("\nIncrease min to RP0...\n"); + writeval(stuff[MIN].filp, origfreqs[RP0]); + check(); + + igt_debug("\nIncrease min above RP0 (invalid)...\n"); + writeval_inval(stuff[MIN].filp, origfreqs[RP0] + 1000); + check(); + + igt_debug("\nDecrease max to RPn (invalid)...\n"); + writeval_inval(stuff[MAX].filp, origfreqs[RPn]); + check(); + + igt_debug("\nDecrease min to midpoint...\n"); + writeval(stuff[MIN].filp, fmid); + check(); + + igt_debug("\nDecrease min to RPn...\n"); + writeval(stuff[MIN].filp, origfreqs[RPn]); + check(); + + igt_debug("\nDecrease min below RPn (invalid)...\n"); + writeval_inval(stuff[MIN].filp, 0); + check(); + + igt_debug("\nDecrease max to midpoint...\n"); + writeval(stuff[MAX].filp, fmid); + check(); + + igt_debug("\nDecrease max to RPn...\n"); + writeval(stuff[MAX].filp, origfreqs[RPn]); + check(); + + igt_debug("\nDecrease max below RPn (invalid)...\n"); + writeval_inval(stuff[MAX].filp, 0); + check(); + + igt_debug("\nIncrease min to RP0 (invalid)...\n"); + writeval_inval(stuff[MIN].filp, origfreqs[RP0]); + check(); + + igt_debug("\nIncrease max to midpoint...\n"); + writeval(stuff[MAX].filp, fmid); + check(); + + igt_debug("\nIncrease max to RP0...\n"); + writeval(stuff[MAX].filp, origfreqs[RP0]); + check(); + + igt_debug("\nIncrease max above RP0 (invalid)...\n"); + writeval_inval(stuff[MAX].filp, origfreqs[RP0] + 1000); + check(); + + writeval(stuff[MIN].filp, origfreqs[MIN]); + writeval(stuff[MAX].filp, origfreqs[MAX]); +} + +static void basic_check(void) +{ + int freqs[NUMFREQ]; + + read_freqs(freqs); + dump(freqs); + checkit(freqs); +} + +#define IDLE_WAIT_TIMESTEP_MSEC 100 +#define IDLE_WAIT_TIMEOUT_MSEC 10000 +static void idle_check(void) +{ + int freqs[NUMFREQ]; + int wait = 0; + + /* Monitor frequencies until cur settles down to min, which should + * happen within the allotted time */ + do { + read_freqs(freqs); + dump(freqs); + checkit(freqs); + if (freqs[CUR] == freqs[MIN]) + break; + usleep(1000 * IDLE_WAIT_TIMESTEP_MSEC); + wait += IDLE_WAIT_TIMESTEP_MSEC; + } while (wait < IDLE_WAIT_TIMEOUT_MSEC); + + igt_assert_cmpint(freqs[CUR], ==, freqs[MIN]); + igt_debug("Required %d msec to reach cur=min\n", wait); +} + +#define LOADED_WAIT_TIMESTEP_MSEC 100 +#define LOADED_WAIT_TIMEOUT_MSEC 3000 +static void loaded_check(void) +{ + int freqs[NUMFREQ]; + int wait = 0; + + /* Monitor frequencies until cur increases to max, which should + * happen within the allotted time */ + do { + read_freqs(freqs); + dump(freqs); + checkit(freqs); + if (freqs[CUR] == freqs[MAX]) + break; + usleep(1000 * LOADED_WAIT_TIMESTEP_MSEC); + wait += LOADED_WAIT_TIMESTEP_MSEC; + } while (wait < LOADED_WAIT_TIMEOUT_MSEC); + + igt_assert_cmpint(freqs[CUR], ==, freqs[MAX]); + igt_debug("Required %d msec to reach cur=max\n", wait); +} + +#define STABILIZE_WAIT_TIMESTEP_MSEC 100 +#define STABILIZE_WAIT_TIMEOUT_MSEC 10000 +static void stabilize_check(int *freqs) +{ + int wait = 0; + + do { + read_freqs(freqs); + dump(freqs); + usleep(1000 * STABILIZE_WAIT_TIMESTEP_MSEC); + wait += STABILIZE_WAIT_TIMESTEP_MSEC; + } while (wait < STABILIZE_WAIT_TIMEOUT_MSEC); + + igt_debug("Waited %d msec to stabilize cur\n", wait); +} + +static void reset(void) +{ + int pre_freqs[NUMFREQ]; + int post_freqs[NUMFREQ]; + + /* + * quiescent_gpu upsets the gpu and makes it get pegged to max somehow. + * Don't ask. + */ + sleep(10); + + igt_debug("Apply low load...\n"); + load_helper_run(LOW); + stabilize_check(pre_freqs); + + igt_debug("Stop rings...\n"); + igt_set_stop_rings(STOP_RING_DEFAULTS); + while (igt_get_stop_rings()) + usleep(1000 * 100); + igt_debug("Ring stop cleared\n"); + + igt_debug("Apply high load...\n"); + load_helper_set_load(HIGH); + loaded_check(); + + igt_debug("Apply low load...\n"); + load_helper_set_load(LOW); + stabilize_check(post_freqs); + matchit(pre_freqs, post_freqs); + + igt_debug("Apply high load...\n"); + load_helper_set_load(HIGH); + loaded_check(); + + igt_debug("Removing load...\n"); + load_helper_stop(); + idle_check(); +} + +static void blocking(void) +{ + int pre_freqs[NUMFREQ]; + int post_freqs[NUMFREQ]; + + int fd = drm_open_any(); + igt_assert(fd >= 0); + + /* + * quiescent_gpu upsets the gpu and makes it get pegged to max somehow. + * Don't ask. + */ + sleep(10); + + igt_debug("Apply low load...\n"); + load_helper_run(LOW); + stabilize_check(pre_freqs); + load_helper_stop(); + + sleep(5); + + igt_debug("Kick gpu hard ...\n"); + /* This relies on the blocking waits in quiescent_gpu and the kernel + * boost logic to ramp the gpu to full load. */ + gem_quiescent_gpu(fd); + gem_quiescent_gpu(fd); + + igt_debug("Apply low load again...\n"); + load_helper_run(LOW); + stabilize_check(post_freqs); + load_helper_stop(); + matchit(pre_freqs, post_freqs); + + igt_debug("Removing load...\n"); + idle_check(); +} + +static void pm_rps_exit_handler(int sig) +{ + if (origfreqs[MIN] > readval(stuff[MAX].filp)) { + writeval(stuff[MAX].filp, origfreqs[MAX]); + writeval(stuff[MIN].filp, origfreqs[MIN]); + } else { + writeval(stuff[MIN].filp, origfreqs[MIN]); + writeval(stuff[MAX].filp, origfreqs[MAX]); + } + + load_helper_deinit(); + close(drm_fd); +} + +igt_main +{ + igt_skip_on_simulation(); + + igt_fixture { + const int device = drm_get_card(); + struct junk *junk = stuff; + int ret; + + /* Use drm_open_any to verify device existence */ + drm_fd = drm_open_any(); + + do { + int val = -1; + char *path; + ret = asprintf(&path, sysfs_base_path, device, junk->name); + igt_assert(ret != -1); + junk->filp = fopen(path, junk->mode); + igt_require(junk->filp); + setbuf(junk->filp, NULL); + + val = readval(junk->filp); + igt_assert(val >= 0); + junk++; + } while(junk->name != NULL); + + read_freqs(origfreqs); + + igt_install_exit_handler(pm_rps_exit_handler); + + load_helper_init(); + } + + igt_subtest("basic-api") + min_max_config(basic_check); + + igt_subtest("min-max-config-idle") + min_max_config(idle_check); + + igt_subtest("min-max-config-loaded") { + load_helper_run(HIGH); + min_max_config(loaded_check); + load_helper_stop(); + } + + igt_subtest("reset") + reset(); + + igt_subtest("blocking") + blocking(); +} diff --git a/tests/prime_nv_api.c b/tests/prime_nv_api.c index 962e903d..99d5cf29 100644 --- a/tests/prime_nv_api.c +++ b/tests/prime_nv_api.c @@ -16,8 +16,10 @@ #include "intel_bufmgr.h" #include "nouveau.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" #include "intel_batchbuffer.h" +#include "drmtest.h" +#include "intel_chipset.h" #define BO_SIZE (256*1024) @@ -29,7 +31,7 @@ struct nouveau_client *nclient, *nclient2; uint32_t devid; struct intel_batchbuffer *intel_batch; -static int find_and_open_devices(void) +static void find_and_open_devices(void) { int i; char path[80]; @@ -38,6 +40,8 @@ static int find_and_open_devices(void) char vendor_id[8]; int venid; for (i = 0; i < 9; i++) { + char *ret; + sprintf(path, "/sys/class/drm/card%d/device/vendor", i); if (stat(path, &buf)) break; @@ -46,166 +50,234 @@ static int find_and_open_devices(void) if (!fl) break; - fgets(vendor_id, 8, fl); + ret = fgets(vendor_id, 8, fl); + igt_assert(ret); fclose(fl); venid = strtoul(vendor_id, NULL, 16); sprintf(path, "/dev/dri/card%d", i); if (venid == 0x8086) { intel_fd = open(path, O_RDWR); - if (!intel_fd) - return -1; + igt_assert(intel_fd); intel_fd2 = open(path, O_RDWR); - if (!intel_fd2) - return -1; + igt_assert(intel_fd2); } else if (venid == 0x10de) { nouveau_fd = open(path, O_RDWR); - if (!nouveau_fd) - return -1; + igt_assert(nouveau_fd); nouveau_fd2 = open(path, O_RDWR); - if (!nouveau_fd2) - return -1; + igt_assert(nouveau_fd2); } } - return 0; } -static int test1(void) +static void test_i915_nv_import_twice(void) { - int ret; drm_intel_bo *test_intel_bo; int prime_fd; struct nouveau_bo *nvbo = NULL, *nvbo2 = NULL; test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096); - ret = drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd); - if (ret) - goto out; + igt_assert(drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd) == 0); - ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo); - if (ret < 0) { - close(prime_fd); - goto out; - } - ret = nouveau_bo_prime_handle_ref(ndev2, prime_fd, &nvbo2); + igt_assert(nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo) == 0); + igt_assert(nouveau_bo_prime_handle_ref(ndev2, prime_fd, &nvbo2) == 0); close(prime_fd); - if (ret < 0) - goto out; - if (nvbo->handle != nvbo2->handle) - ret = -1; -out: nouveau_bo_ref(NULL, &nvbo2); nouveau_bo_ref(NULL, &nvbo); drm_intel_bo_unreference(test_intel_bo); - return ret; } +static void test_i915_nv_import_twice_check_flink_name(void) +{ + drm_intel_bo *test_intel_bo; + int prime_fd; + struct nouveau_bo *nvbo = NULL, *nvbo2 = NULL; + uint32_t flink_name1, flink_name2; + + test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096); + + igt_assert(drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd) == 0); + + igt_assert(nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo) == 0); + igt_assert(nouveau_bo_prime_handle_ref(ndev2, prime_fd, &nvbo2) == 0); + close(prime_fd); + + igt_assert(nouveau_bo_name_get(nvbo, &flink_name1) == 0); + igt_assert(nouveau_bo_name_get(nvbo2, &flink_name2) == 0); + + igt_assert(flink_name1 == flink_name2); -static int test2(void) + nouveau_bo_ref(NULL, &nvbo2); + nouveau_bo_ref(NULL, &nvbo); + drm_intel_bo_unreference(test_intel_bo); +} + +static void test_i915_nv_reimport_twice_check_flink_name(void) { - int ret; drm_intel_bo *test_intel_bo; int prime_fd; struct nouveau_bo *nvbo = NULL, *nvbo2 = NULL; + uint32_t flink_name1, flink_name2; test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096); - ret = drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd); - if (ret < 0) - goto out; + igt_assert(drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd) == 0); + + igt_assert(nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo) == 0); - ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo); + /* create a new dma-buf */ close(prime_fd); - if (ret < 0) - goto out; - ret = nouveau_bo_prime_handle_ref(ndev2, prime_fd, &nvbo2); - if (ret == 0) - ret = -1; - else - ret = 0; - -out: + igt_assert(drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd) == 0); + + igt_assert(nouveau_bo_prime_handle_ref(ndev2, prime_fd, &nvbo2) == 0); + close(prime_fd); + + igt_assert(nouveau_bo_name_get(nvbo, &flink_name1) == 0); + igt_assert(nouveau_bo_name_get(nvbo2, &flink_name2) == 0); + + igt_assert(flink_name1 == flink_name2); + nouveau_bo_ref(NULL, &nvbo2); nouveau_bo_ref(NULL, &nvbo); drm_intel_bo_unreference(test_intel_bo); - return ret; } +static void test_nv_i915_import_twice_check_flink_name(void) +{ + drm_intel_bo *intel_bo = NULL, *intel_bo2 = NULL; + int prime_fd; + struct nouveau_bo *nvbo = NULL; + uint32_t flink_name1, flink_name2; + + igt_assert(nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, + 0, BO_SIZE, NULL, &nvbo) == 0); + + igt_assert(nouveau_bo_set_prime(nvbo, &prime_fd) == 0); + + intel_bo = drm_intel_bo_gem_create_from_prime(bufmgr, prime_fd, BO_SIZE); + igt_assert(intel_bo); + + intel_bo2 = drm_intel_bo_gem_create_from_prime(bufmgr2, prime_fd, BO_SIZE); + igt_assert(intel_bo2); + close(prime_fd); + + igt_assert(drm_intel_bo_flink(intel_bo, &flink_name1) == 0); + igt_assert(drm_intel_bo_flink(intel_bo2, &flink_name2) == 0); + + igt_assert(flink_name1 == flink_name2); + + nouveau_bo_ref(NULL, &nvbo); + drm_intel_bo_unreference(intel_bo); + drm_intel_bo_unreference(intel_bo2); +} + +static void test_nv_i915_reimport_twice_check_flink_name(void) +{ + drm_intel_bo *intel_bo = NULL, *intel_bo2 = NULL; + int prime_fd; + struct nouveau_bo *nvbo = NULL; + uint32_t flink_name1, flink_name2; + + igt_assert(nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, + 0, BO_SIZE, NULL, &nvbo) == 0); + + igt_assert(nouveau_bo_set_prime(nvbo, &prime_fd) == 0); + + intel_bo = drm_intel_bo_gem_create_from_prime(bufmgr, prime_fd, BO_SIZE); + igt_assert(intel_bo); + close(prime_fd); + igt_assert(nouveau_bo_set_prime(nvbo, &prime_fd) == 0); + + intel_bo2 = drm_intel_bo_gem_create_from_prime(bufmgr2, prime_fd, BO_SIZE); + igt_assert(intel_bo2); + close(prime_fd); + + igt_assert(drm_intel_bo_flink(intel_bo, &flink_name1) == 0); + igt_assert(drm_intel_bo_flink(intel_bo2, &flink_name2) == 0); + + igt_assert(flink_name1 == flink_name2); + + nouveau_bo_ref(NULL, &nvbo); + drm_intel_bo_unreference(intel_bo); + drm_intel_bo_unreference(intel_bo2); +} + +static void test_i915_nv_import_vs_close(void) +{ + drm_intel_bo *test_intel_bo; + int prime_fd; + struct nouveau_bo *nvbo = NULL, *nvbo2 = NULL; + + test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096); + igt_assert(test_intel_bo); + + igt_assert(drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd) == 0); + + igt_assert(nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo) == 0); + close(prime_fd); + igt_assert(nouveau_bo_prime_handle_ref(ndev2, prime_fd, &nvbo2) < 0); + + nouveau_bo_ref(NULL, &nvbo2); + nouveau_bo_ref(NULL, &nvbo); + drm_intel_bo_unreference(test_intel_bo); +} /* import handle twice on one driver */ -static int test3(void) +static void test_i915_nv_double_import(void) { - int ret; drm_intel_bo *test_intel_bo; int prime_fd; struct nouveau_bo *nvbo = NULL, *nvbo2 = NULL; test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096); + igt_assert(test_intel_bo); - ret = drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd); - if (ret < 0) - goto out; + igt_assert(drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd) == 0); - ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo); - if (ret < 0) { - close(prime_fd); - goto out; - } - ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo2); + igt_assert(nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo) == 0); + igt_assert(nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo2) == 0); close(prime_fd); - if (ret < 0) - goto out; - if (nvbo->handle != nvbo2->handle) - ret = -1; + igt_assert(nvbo->handle == nvbo2->handle); -out: nouveau_bo_ref(NULL, &nvbo2); nouveau_bo_ref(NULL, &nvbo); drm_intel_bo_unreference(test_intel_bo); - return ret; } /* export handle twice from one driver - import twice see if we get same object */ -static int test4(void) +static void test_i915_nv_double_export(void) { - int ret; drm_intel_bo *test_intel_bo; int prime_fd, prime_fd2; struct nouveau_bo *nvbo = NULL, *nvbo2 = NULL; test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096); + igt_assert(test_intel_bo); drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd); drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd2); - ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo); + igt_assert(nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo) == 0); close(prime_fd); - if (ret >= 0) - ret = nouveau_bo_prime_handle_ref(ndev, prime_fd2, &nvbo2); + igt_assert(nouveau_bo_prime_handle_ref(ndev, prime_fd2, &nvbo2) == 0); close(prime_fd2); - if (ret < 0) - goto out; - if (nvbo->handle != nvbo2->handle) - ret = -1; + igt_assert(nvbo->handle == nvbo2->handle); -out: nouveau_bo_ref(NULL, &nvbo2); nouveau_bo_ref(NULL, &nvbo); drm_intel_bo_unreference(test_intel_bo); - return ret; } /* export handle from intel driver - reimport to intel driver see if you get same object */ -static int test5(void) +static void test_i915_self_import(void) { - int ret; drm_intel_bo *test_intel_bo, *test_intel_bo2; int prime_fd; @@ -215,52 +287,35 @@ static int test5(void) test_intel_bo2 = drm_intel_bo_gem_create_from_prime(bufmgr, prime_fd, BO_SIZE); close(prime_fd); - if (!test_intel_bo2) { - ret = -1; - goto out; - } + igt_assert(test_intel_bo2); - ret = 0; - if (test_intel_bo->handle != test_intel_bo2->handle) - ret = -1; + igt_assert(test_intel_bo->handle == test_intel_bo2->handle); -out: drm_intel_bo_unreference(test_intel_bo); - return ret; } /* nouveau export reimport test */ -static int test6(void) +static void test_nv_self_import(void) { - int ret; int prime_fd; struct nouveau_bo *nvbo, *nvbo2; - ret = nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, - 0, BO_SIZE, NULL, &nvbo); - if (ret < 0) - return ret; - ret = nouveau_bo_set_prime(nvbo, &prime_fd); - if (ret < 0) - return ret; + igt_assert(nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, + 0, BO_SIZE, NULL, &nvbo) == 0); + igt_assert(nouveau_bo_set_prime(nvbo, &prime_fd) == 0); - ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo2); + igt_assert(nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo2) == 0); close(prime_fd); - if (ret < 0) - return ret; - if (nvbo->handle != nvbo2->handle) - fprintf(stderr,"mismatch handles %d %d\n", nvbo->handle, nvbo2->handle); + igt_assert(nvbo->handle == nvbo2->handle); nouveau_bo_ref(NULL, &nvbo); nouveau_bo_ref(NULL, &nvbo2); - return 0; } /* export handle from intel driver - reimport to another intel driver bufmgr see if you get same object */ -static int test7(void) +static void test_i915_self_import_to_different_fd(void) { - int ret; drm_intel_bo *test_intel_bo, *test_intel_bo2; int prime_fd; @@ -270,139 +325,89 @@ static int test7(void) test_intel_bo2 = drm_intel_bo_gem_create_from_prime(bufmgr2, prime_fd, BO_SIZE); close(prime_fd); - if (!test_intel_bo2) { - ret = -1; - goto out; - } + igt_assert(test_intel_bo2); - ret = 0; - /* not sure what to test for, just that we don't explode */ -out: drm_intel_bo_unreference(test_intel_bo2); drm_intel_bo_unreference(test_intel_bo); - return ret; } /* nouveau export reimport to other driver test */ -static int test8(void) +static void test_nv_self_import_to_different_fd(void) { - int ret; int prime_fd; struct nouveau_bo *nvbo, *nvbo2; - ret = nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, - 0, BO_SIZE, NULL, &nvbo); - if (ret < 0) - return ret; - ret = nouveau_bo_set_prime(nvbo, &prime_fd); - if (ret < 0) - return ret; + igt_assert(nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, + 0, BO_SIZE, NULL, &nvbo) == 0); + igt_assert(nouveau_bo_set_prime(nvbo, &prime_fd) == 0); - ret = nouveau_bo_prime_handle_ref(ndev2, prime_fd, &nvbo2); + igt_assert(nouveau_bo_prime_handle_ref(ndev2, prime_fd, &nvbo2) == 0); close(prime_fd); - if (ret < 0) - return ret; /* not sure what to test for, just make sure we don't explode */ nouveau_bo_ref(NULL, &nvbo); nouveau_bo_ref(NULL, &nvbo2); - return 0; } -int main(int argc, char **argv) +igt_main { - int ret; + igt_fixture { + find_and_open_devices(); - ret = find_and_open_devices(); - if (ret < 0) - return ret; + igt_require(nouveau_fd != -1); + igt_require(nouveau_fd2 != -1); + igt_require(intel_fd != -1); + igt_require(intel_fd2 != -1); - if (nouveau_fd == -1 || intel_fd == -1 || nouveau_fd2 == -1 || intel_fd2 == -1) { - fprintf(stderr,"failed to find intel and nouveau GPU\n"); - return 77; - } - - /* set up intel bufmgr */ - bufmgr = drm_intel_bufmgr_gem_init(intel_fd, 4096); - if (!bufmgr) - return -1; - /* Do not enable reuse, we share (almost) all buffers. */ - //drm_intel_bufmgr_gem_enable_reuse(bufmgr); - - bufmgr2 = drm_intel_bufmgr_gem_init(intel_fd2, 4096); - if (!bufmgr2) - return -1; - drm_intel_bufmgr_gem_enable_reuse(bufmgr2); - - /* set up nouveau bufmgr */ - ret = nouveau_device_wrap(nouveau_fd, 0, &ndev); - if (ret < 0) { - fprintf(stderr,"failed to wrap nouveau device\n"); - return 77; - } + /* set up intel bufmgr */ + bufmgr = drm_intel_bufmgr_gem_init(intel_fd, 4096); + igt_assert(bufmgr); + /* Do not enable reuse, we share (almost) all buffers. */ + //drm_intel_bufmgr_gem_enable_reuse(bufmgr); - ret = nouveau_client_new(ndev, &nclient); - if (ret < 0) { - fprintf(stderr,"failed to setup nouveau client\n"); - return -1; - } - - /* set up nouveau bufmgr */ - ret = nouveau_device_wrap(nouveau_fd2, 0, &ndev2); - if (ret < 0) { - fprintf(stderr,"failed to wrap nouveau device\n"); - return 77; - } - - ret = nouveau_client_new(ndev2, &nclient2); - if (ret < 0) { - fprintf(stderr,"failed to setup nouveau client\n"); - return -1; - } + bufmgr2 = drm_intel_bufmgr_gem_init(intel_fd2, 4096); + igt_assert(bufmgr2); + drm_intel_bufmgr_gem_enable_reuse(bufmgr2); - /* set up an intel batch buffer */ - devid = intel_get_drm_devid(intel_fd); - intel_batch = intel_batchbuffer_alloc(bufmgr, devid); + /* set up nouveau bufmgr */ + igt_assert(nouveau_device_wrap(nouveau_fd, 0, &ndev) >= 0); + igt_assert(nouveau_client_new(ndev, &nclient) >= 0); - ret = test1(); - if (ret) - fprintf(stderr,"prime_test: failed test 1\n"); + /* set up nouveau bufmgr */ + igt_assert(nouveau_device_wrap(nouveau_fd2, 0, &ndev2) >= 0); - ret = test2(); - if (ret) - fprintf(stderr,"prime_test: failed test 2\n"); + igt_assert(nouveau_client_new(ndev2, &nclient2) >= 0);; - ret = test3(); - if (ret) - fprintf(stderr,"prime_test: failed test 3\n"); - - ret = test4(); - if (ret) - fprintf(stderr,"prime_test: failed test 4\n"); - - ret = test5(); - if (ret) - fprintf(stderr,"prime_test: failed test 5\n"); - - ret = test6(); - if (ret) - fprintf(stderr,"prime_test: failed test 6\n"); - - ret = test7(); - if (ret) - fprintf(stderr,"prime_test: failed test 7\n"); - - ret = test8(); - if (ret) - fprintf(stderr,"prime_test: failed test 8\n"); - - intel_batchbuffer_free(intel_batch); - - nouveau_device_del(&ndev); - drm_intel_bufmgr_destroy(bufmgr); - - close(intel_fd); - close(nouveau_fd); + /* set up an intel batch buffer */ + devid = intel_get_drm_devid(intel_fd); + intel_batch = intel_batchbuffer_alloc(bufmgr, devid); + igt_assert(intel_batch); + } - return ret; +#define xtest(name) \ + igt_subtest(#name) \ + test_##name(); + + xtest(i915_nv_import_twice); + xtest(i915_nv_import_twice_check_flink_name); + xtest(i915_nv_reimport_twice_check_flink_name); + xtest(nv_i915_import_twice_check_flink_name); + xtest(nv_i915_reimport_twice_check_flink_name); + xtest(i915_nv_import_vs_close); + xtest(i915_nv_double_import); + xtest(i915_nv_double_export); + xtest(i915_self_import); + xtest(nv_self_import); + xtest(i915_self_import_to_different_fd); + xtest(nv_self_import_to_different_fd); + + igt_fixture { + intel_batchbuffer_free(intel_batch); + + nouveau_device_del(&ndev); + drm_intel_bufmgr_destroy(bufmgr); + + close(intel_fd); + close(nouveau_fd); + } } diff --git a/tests/prime_nv_pcopy.c b/tests/prime_nv_pcopy.c index 21dccf38..fb0f62ff 100644 --- a/tests/prime_nv_pcopy.c +++ b/tests/prime_nv_pcopy.c @@ -23,11 +23,13 @@ #include <sys/ioctl.h> #include <errno.h> -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "intel_bufmgr.h" #include "nouveau.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" #include "intel_batchbuffer.h" +#include "intel_chipset.h" +#include "drmtest.h" static int intel_fd = -1, nouveau_fd = -1; static drm_intel_bufmgr *bufmgr; @@ -49,24 +51,17 @@ static uint32_t memtype_intel, tile_intel_y, tile_intel_x; #define NV01_SUBC(subc, mthd) SUBC_##subc((NV01_SUBCHAN_##mthd)) -#if 0 -#define dbg(fmt...) fprintf(stderr, fmt); -#else -#define dbg(...) do { } while (0) -#endif - typedef struct { uint32_t w, h; uint32_t pitch, lines; } rect; -static int nv_bo_alloc(struct nouveau_bo **bo, rect *r, - uint32_t w, uint32_t h, uint32_t tile_mode, - int handle, uint32_t dom) +static void nv_bo_alloc(struct nouveau_bo **bo, rect *r, + uint32_t w, uint32_t h, uint32_t tile_mode, + int handle, uint32_t dom) { uint32_t size; uint32_t dx = 1, dy = 1, memtype = 0; - int ret; *bo = NULL; if (tile_mode) { @@ -92,7 +87,7 @@ static int nv_bo_alloc(struct nouveau_bo **bo, rect *r, dx = 1 << tile_x; dy = 1 << tile_y; - dbg("Tiling requirements: x y %u %u\n", dx, dy); + igt_debug("Tiling requirements: x y %u %u\n", dx, dy); } r->w = w; @@ -108,43 +103,31 @@ static int nv_bo_alloc(struct nouveau_bo **bo, rect *r, cfg.nv50.tile_mode = tile_mode; if (dom == NOUVEAU_BO_GART) dom |= NOUVEAU_BO_MAP; - ret = nouveau_bo_new(ndev, dom, 4096, size, &cfg, bo); - if (!ret) - ret = nouveau_bo_map(*bo, NOUVEAU_BO_RDWR, nclient); - if (ret) { - fprintf(stderr, "creating bo failed with %i %s\n", - ret, strerror(-ret)); - nouveau_bo_ref(NULL, bo); - return ret; - } + igt_assert(nouveau_bo_new(ndev, dom, 4096, size, &cfg, bo) == 0); + igt_assert(nouveau_bo_map(*bo, NOUVEAU_BO_RDWR, nclient) == 0); - dbg("new flags %08x memtype %08x tile %08x\n", (*bo)->flags, (*bo)->config.nv50.memtype, (*bo)->config.nv50.tile_mode); + igt_debug("new flags %08x memtype %08x tile %08x\n", + (*bo)->flags, (*bo)->config.nv50.memtype, + (*bo)->config.nv50.tile_mode); if (tile_mode == tile_intel_y || tile_mode == tile_intel_x) { - dbg("tile mode was: %02x, now: %02x\n", (*bo)->config.nv50.tile_mode, tile_mode); + igt_debug("tile mode was: %02x, now: %02x\n", + (*bo)->config.nv50.tile_mode, tile_mode); /* Doesn't like intel tiling much.. */ (*bo)->config.nv50.tile_mode = tile_mode; } } else { - ret = nouveau_bo_prime_handle_ref(ndev, handle, bo); + igt_assert(nouveau_bo_prime_handle_ref(ndev, handle, bo) == 0); close(handle); - if (ret < 0) { - fprintf(stderr, "receiving bo failed with %i %s\n", - ret, strerror(-ret)); - return ret; - } - if ((*bo)->size < size) { - fprintf(stderr, "expected bo size to be at least %u," - "but received %"PRIu64"\n", size, (*bo)->size); - nouveau_bo_ref(NULL, bo); - return -1; - } - dbg("prime flags %08x memtype %08x tile %08x\n", (*bo)->flags, (*bo)->config.nv50.memtype, (*bo)->config.nv50.tile_mode); + igt_assert_f((*bo)->size >= size, + "expected bo size to be at least %u," + "but received %"PRIu64"\n", size, (*bo)->size); + igt_debug("prime flags %08x memtype %08x tile %08x\n", + (*bo)->flags, (*bo)->config.nv50.memtype, + (*bo)->config.nv50.tile_mode); (*bo)->config.nv50.memtype = memtype; (*bo)->config.nv50.tile_mode = tile_mode; } - dbg("size: %"PRIu64"\n", (*bo)->size); - - return ret; + igt_debug("size: %"PRIu64"\n", (*bo)->size); } static inline void @@ -193,7 +176,7 @@ noop_intel(drm_intel_bo *bo) intel_batchbuffer_flush(batch); } -static int find_and_open_devices(void) +static void find_and_open_devices(void) { int i; char path[80], *unused; @@ -218,57 +201,37 @@ static int find_and_open_devices(void) sprintf(path, "/dev/dri/card%d", i); if (venid == 0x8086) { intel_fd = open(path, O_RDWR); - if (!intel_fd) - return -1; + igt_assert(intel_fd); } else if (venid == 0x10de) { nouveau_fd = open(path, O_RDWR); - if (!nouveau_fd) - return -1; + igt_assert(nouveau_fd); } } - return 0; } -static int init_nouveau(void) +static void init_nouveau(void) { struct nv04_fifo nv04_data = { .vram = 0xbeef0201, .gart = 0xbeef0202 }; struct nvc0_fifo nvc0_data = { }; struct nouveau_fifo *fifo; - int size, ret; + int size; uint32_t class; void *data; - ret = nouveau_device_wrap(nouveau_fd, 0, &ndev); - if (ret < 0) { - fprintf(stderr,"failed to wrap nouveau device\n"); - return ret; - } + igt_assert(nouveau_device_wrap(nouveau_fd, 0, &ndev) == 0); - ret = nouveau_client_new(ndev, &nclient); - if (ret < 0) { - fprintf(stderr,"failed to setup nouveau client\n"); - return ret; - } + igt_assert(nouveau_client_new(ndev, &nclient) == 0); - if (ndev->chipset < 0xa3 || ndev->chipset == 0xaa || ndev->chipset == 0xac) { - fprintf(stderr, "Your card doesn't support PCOPY\n"); - return -1; - } + igt_skip_on_f(ndev->chipset < 0xa3 || ndev->chipset == 0xaa || ndev->chipset == 0xac, + "Your card doesn't support PCOPY\n"); // TODO: Get a kepler and add support for it - if (ndev->chipset >= 0xe0) { - fprintf(stderr, "Unsure how kepler works!\n"); - return -1; - } - ret = nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, - 4096, 4096, NULL, &query_bo); - if (!ret) - ret = nouveau_bo_map(query_bo, NOUVEAU_BO_RDWR, nclient); - if (ret < 0) { - fprintf(stderr,"failed to setup query counter\n"); - return ret; - } + igt_skip_on_f(ndev->chipset >= 0xe0, + "Unsure how kepler works!\n"); + igt_assert(nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, + 4096, 4096, NULL, &query_bo) == 0); + igt_assert(nouveau_bo_map(query_bo, NOUVEAU_BO_RDWR, nclient) == 0); query = query_bo->map; *query = query_counter; @@ -282,45 +245,22 @@ static int init_nouveau(void) size = sizeof(nvc0_data); } - ret = nouveau_object_new(&ndev->object, 0, NOUVEAU_FIFO_CHANNEL_CLASS, - data, size, &nchannel); - if (ret) { - fprintf(stderr, "Error creating GPU channel: %d\n", ret); - if (ret == -ENODEV) { - fprintf(stderr, "Make sure nouveau_accel is active\n"); - fprintf(stderr, "nvd9 is likely broken regardless\n"); - } - return ret; - } + igt_assert(nouveau_object_new(&ndev->object, 0, NOUVEAU_FIFO_CHANNEL_CLASS, + data, size, &nchannel) == 0); fifo = nchannel->data; - ret = nouveau_pushbuf_new(nclient, nchannel, 4, 32 * 1024, - true, &npush); - if (ret) { - fprintf(stderr, "Error allocating DMA push buffer: %d\n", ret); - return ret; - } + igt_assert(nouveau_pushbuf_new(nclient, nchannel, 4, 32 * 1024, + true, &npush) == 0); - ret = nouveau_bufctx_new(nclient, 1, &nbufctx); - if (ret) { - fprintf(stderr, "Error allocating buffer context: %d\n", ret); - return ret; - } + igt_assert(nouveau_bufctx_new(nclient, 1, &nbufctx) == 0); npush->user_priv = nbufctx; /* Hope this is enough init for PCOPY */ - ret = nouveau_object_new(nchannel, class, class & 0xffff, NULL, 0, &pcopy); - if (ret) { - fprintf(stderr, "Failed to allocate pcopy: %d\n", ret); - return ret; - } - ret = nouveau_pushbuf_space(npush, 512, 0, 0); - if (ret) { - fprintf(stderr, "No space in pushbuf: %d\n", ret); - return ret; - } + igt_assert(nouveau_object_new(nchannel, class, class & 0xffff, NULL, 0, &pcopy) == 0); + igt_assert(nouveau_pushbuf_space(npush, 512, 0, 0) == 0); + if (ndev->chipset < 0xc0) { struct nv04_fifo *nv04_fifo = (struct nv04_fifo*)fifo; tile_intel_y = 0x3e; @@ -339,7 +279,6 @@ static int init_nouveau(void) PUSH_DATA(npush, pcopy->handle); } nouveau_pushbuf_kick(npush, npush->channel); - return ret; } static void fill16(void *ptr, uint32_t val) @@ -351,12 +290,12 @@ static void fill16(void *ptr, uint32_t val) #define TILE_SIZE 4096 -static int swtile_y(uint8_t *out, const uint8_t *in, int w, int h) +static void swtile_y(uint8_t *out, const uint8_t *in, int w, int h) { uint32_t x, y, dx, dy; uint8_t *endptr = out + w * h; - assert(!(w % 128)); - assert(!(h % 32)); + igt_assert(!(w % 128)); + igt_assert(!(h % 32)); for (y = 0; y < h; y += 32) { for (x = 0; x < w; x += 128, out += TILE_SIZE) { @@ -364,8 +303,8 @@ static int swtile_y(uint8_t *out, const uint8_t *in, int w, int h) for (dy = 0; dy < 32; ++dy) { uint32_t out_ofs = (dx * 32 + dy) * 16; uint32_t in_ofs = (y + dy) * w + (x + 16 * dx); - assert(out_ofs < TILE_SIZE); - assert(in_ofs < w*h); + igt_assert(out_ofs < TILE_SIZE); + igt_assert(in_ofs < w*h); // To do the Y tiling quirk: // out_ofs = out_ofs ^ (((out_ofs >> 9) & 1) << 6); @@ -374,158 +313,36 @@ static int swtile_y(uint8_t *out, const uint8_t *in, int w, int h) } } } - assert(out == endptr); - return 0; + igt_assert(out == endptr); } -static int swtile_x(uint8_t *out, const uint8_t *in, int w, int h) +static void swtile_x(uint8_t *out, const uint8_t *in, int w, int h) { uint32_t x, y, dy; uint8_t *endptr = out + w * h; - assert(!(w % 512)); - assert(!(h % 8)); + igt_assert(!(w % 512)); + igt_assert(!(h % 8)); for (y = 0; y < h; y += 8) { for (x = 0; x < w; x += 512, out += TILE_SIZE) { for (dy = 0; dy < 8; ++dy) { uint32_t out_ofs = 512 * dy; uint32_t in_ofs = (y + dy) * w + x; - assert(out_ofs < TILE_SIZE); - assert(in_ofs < w*h); + igt_assert(out_ofs < TILE_SIZE); + igt_assert(in_ofs < w*h); memcpy(&out[out_ofs], &in[in_ofs], 512); } } } - assert(out == endptr); - return 0; -} - -#if 0 -/* X tiling is approximately linear, except tiled in 512x8 blocks, so lets abuse that - * - * How? Whole contiguous tiles can be copied safely as if linear - */ - -static int perform_copy_hack(struct nouveau_bo *nvbo, const rect *dst, - uint32_t dst_x, uint32_t dst_y, - struct nouveau_bo *nvbi, const rect *src, - uint32_t src_x, uint32_t src_y, - uint32_t w, uint32_t h) -{ - struct nouveau_pushbuf_refn refs[] = { - { nvbi, (nvbi->flags & NOUVEAU_BO_APER) | NOUVEAU_BO_RD }, - { nvbo, (nvbo->flags & NOUVEAU_BO_APER) | NOUVEAU_BO_WR }, - { query_bo, NOUVEAU_BO_GART | NOUVEAU_BO_RDWR } - }; - uint32_t exec = 0x00000000; - uint32_t src_off = 0, dst_off = 0; - struct nouveau_pushbuf *push = npush; - uint32_t dw, tiles, tile_src = nvbi->config.nv50.tile_mode, tile_dst = nvbo->config.nv50.tile_mode; - - if (tile_src == tile_intel_x) - dw = 512 - (src_x & 512); - else - dw = 512 - (dst_x % 512); - - if (!nvbi->config.nv50.memtype) - exec |= 0x00000010; - if (!tile_src) - src_off = src_y * src->pitch + src_x; - - if (!nvbo->config.nv50.memtype) - exec |= 0x00000100; - if (!tile_dst) - dst_off = dst_y * dst->pitch + dst_x; - - if (dw > w) - dw = w; - tiles = 1 + ((w - dw + 511)/512); - - if (nouveau_pushbuf_space(push, 8 + tiles * 32, 0, 0) || - nouveau_pushbuf_refn(push, refs, 3)) - return -1; - - for (; w; w -= dw, src_x += dw, dst_x += dw, dw = w > 512 ? 512 : w) { - if (tile_src == tile_intel_x) { - /* Find the correct tiled offset */ - src_off = 8 * dst->pitch * (src_y / 8); - src_off += src_x / 512 * 4096; - src_off += (src_x % 512) + 512 * (src_y % 8); - - if (!tile_dst) - dst_off = dst_y * dst->pitch + dst_x; - } else { - if (!tile_src) - src_off = src_y * src->pitch + src_x; - - dst_off = 8 * dst->pitch * (dst_y / 8); - dst_off += dst_x / 512 * 4096; - dst_off += (dst_x % 512) + 512 * (dst_y % 8); - } - - fprintf(stderr, "Copying from %u to %u for %u bytes\n", src_x, dst_x, dw); - fprintf(stderr, "src ofs: %u, dst ofs: %u\n", src_off, dst_off); - BEGIN_NVXX(push, SUBC_COPY(0x0200), 7); - PUSH_DATA (push, tile_src == tile_intel_x ? 0 : nvbi->config.nv50.tile_mode); - PUSH_DATA (push, src->pitch); - PUSH_DATA (push, src->h); - PUSH_DATA (push, 1); - PUSH_DATA (push, 0); - PUSH_DATA (push, src_x); - PUSH_DATA (push, src_y); - - BEGIN_NVXX(push, SUBC_COPY(0x0220), 7); - PUSH_DATA (push, tile_dst == tile_intel_x ? 0 : nvbo->config.nv50.tile_mode); - PUSH_DATA (push, dst->pitch); - PUSH_DATA (push, dst->h); - PUSH_DATA (push, 1); - PUSH_DATA (push, 0); - PUSH_DATA (push, dst_x); - PUSH_DATA (push, dst_y); - - BEGIN_NVXX(push, SUBC_COPY(0x030c), 8); - PUSH_DATA (push, (nvbi->offset + src_off) >> 32); - PUSH_DATA (push, (nvbi->offset + src_off)); - PUSH_DATA (push, (nvbo->offset + dst_off) >> 32); - PUSH_DATA (push, (nvbo->offset + dst_off)); - PUSH_DATA (push, src->pitch); - PUSH_DATA (push, dst->pitch); - PUSH_DATA (push, dw); - PUSH_DATA (push, h); - - if (w == dw) { - exec |= 0x3000; /* QUERY|QUERY_SHORT */ - BEGIN_NVXX(push, SUBC_COPY(0x0338), 3); - PUSH_DATA (push, (query_bo->offset) >> 32); - PUSH_DATA (push, (query_bo->offset)); - PUSH_DATA (push, ++query_counter); - } - - BEGIN_NVXX(push, SUBC_COPY(0x0300), 1); - PUSH_DATA (push, exec); - } - nouveau_pushbuf_kick(push, push->channel); - while (*query < query_counter) { } - return 0; + igt_assert(out == endptr); } -#endif -static int perform_copy(struct nouveau_bo *nvbo, const rect *dst, - uint32_t dst_x, uint32_t dst_y, - struct nouveau_bo *nvbi, const rect *src, - uint32_t src_x, uint32_t src_y, - uint32_t w, uint32_t h) +static void perform_copy(struct nouveau_bo *nvbo, const rect *dst, + uint32_t dst_x, uint32_t dst_y, + struct nouveau_bo *nvbi, const rect *src, + uint32_t src_x, uint32_t src_y, + uint32_t w, uint32_t h) { -#if 0 - /* Too much effort */ - if (nvbi->config.nv50.tile_mode == tile_intel_x && - nvbo->config.nv50.tile_mode == tile_intel_x) - return -1; - else if (nvbi->config.nv50.tile_mode == tile_intel_x || - nvbo->config.nv50.tile_mode == tile_intel_x) - return perform_copy_hack(nvbo, dst, dst_x, dst_y, - nvbi, src, src_x, src_y, w, h); -#endif struct nouveau_pushbuf_refn refs[] = { { nvbi, (nvbi->flags & NOUVEAU_BO_APER) | NOUVEAU_BO_RD }, { nvbo, (nvbo->flags & NOUVEAU_BO_APER) | NOUVEAU_BO_WR }, @@ -534,15 +351,15 @@ static int perform_copy(struct nouveau_bo *nvbo, const rect *dst, uint32_t cpp = 1, exec = 0x00003000; /* QUERY|QUERY_SHORT|FORMAT */ uint32_t src_off = 0, dst_off = 0; struct nouveau_pushbuf *push = npush; + int ret; if (nvbi->config.nv50.tile_mode == tile_intel_y) - dbg("src is y-tiled\n"); + igt_debug("src is y-tiled\n"); if (nvbo->config.nv50.tile_mode == tile_intel_y) - dbg("dst is y-tiled\n"); + igt_debug("dst is y-tiled\n"); - if (nouveau_pushbuf_space(push, 64, 0, 0) || - nouveau_pushbuf_refn(push, refs, 3)) - return -1; + igt_assert(nouveau_pushbuf_space(push, 64, 0, 0) == 0); + igt_assert(nouveau_pushbuf_refn(push, refs, 3) == 0); if (!nvbi->config.nv50.tile_mode) { src_off = src_y * src->pitch + src_x; @@ -591,73 +408,62 @@ static int perform_copy(struct nouveau_bo *nvbo, const rect *dst, BEGIN_NVXX(push, SUBC_COPY(0x0300), 1); PUSH_DATA (push, exec); - nouveau_pushbuf_kick(push, push->channel); - while (*query < query_counter) { usleep(1000); } - return 0; + ret = nouveau_pushbuf_kick(push, push->channel); + while (!ret && *query < query_counter) { usleep(1000); } + + igt_assert(ret == 0); } -static int check1_macro(uint32_t *p, uint32_t w, uint32_t h) +static void check1_macro(uint32_t *p, uint32_t w, uint32_t h) { uint32_t i, val, j; for (i = 0; i < 256; ++i, p += 4) { val = (i) | (i << 8) | (i << 16) | (i << 24); - if (p[0] != val || p[1] != val || p[2] != val || p[3] != val) { - fprintf(stderr, "Retile check failed in first tile!\n"); - fprintf(stderr, "%08x %08x %08x %08x instead of %08x\n", - p[0], p[1], p[2], p[3], val); - return -1; - } + igt_assert_f(p[0] == val && p[1] == val && p[2] == val && p[3] == val, + "Retile check failed in first tile!\n" + "%08x %08x %08x %08x instead of %08x\n", + p[0], p[1], p[2], p[3], val); } val = 0x3e3e3e3e; for (i = 0; i < 256 * (w-1); ++i, p += 4) { - if (p[0] != val || p[1] != val || p[2] != val || p[3] != val) { - fprintf(stderr, "Retile check failed in second tile!\n"); - fprintf(stderr, "%08x %08x %08x %08x instead of %08x\n", - p[0], p[1], p[2], p[3], val); - return -1; - } + igt_assert_f(p[0] == val && p[1] == val && p[2] == val && p[3] == val, + "Retile check failed in second tile!\n" + "%08x %08x %08x %08x instead of %08x\n", + p[0], p[1], p[2], p[3], val); } for (j = 1; j < h; ++j) { val = 0x7e7e7e7e; for (i = 0; i < 256; ++i, p += 4) { - if (p[0] != val || p[1] != val || p[2] != val || p[3] != val) { - fprintf(stderr, "Retile check failed in third tile!\n"); - fprintf(stderr, "%08x %08x %08x %08x instead of %08x\n", - p[0], p[1], p[2], p[3], val); - return -1; - } + igt_assert_f(p[0] == val && p[1] == val && p[2] == val && p[3] == val, + "Retile check failed in third tile!\n" + "%08x %08x %08x %08x instead of %08x\n", + p[0], p[1], p[2], p[3], val); } val = 0xcececece; for (i = 0; i < 256 * (w-1); ++i, p += 4) { - if (p[0] != val || p[1] != val || p[2] != val || p[3] != val) { - fprintf(stderr, "Retile check failed in fourth tile!\n"); - fprintf(stderr, "%08x %08x %08x %08x instead of %08x\n", - p[0], p[1], p[2], p[3], val); - return -1; - } + igt_assert_f(p[0] == val && p[1] == val && p[2] == val && p[3] == val, + "Retile check failed in fourth tile!\n" + "%08x %08x %08x %08x instead of %08x\n", + p[0], p[1], p[2], p[3], val); } } - return 0; } /* test 1, see if we can copy from linear to intel Y format safely */ -static int test1_macro(void) +static void test1_macro(void) { - int ret, prime_fd = -1; + int prime_fd = -1; struct nouveau_bo *nvbo = NULL, *nvbi = NULL; rect dst, src; uint8_t *ptr; uint32_t w = 2 * 128, h = 2 * 32, x, y; - ret = nv_bo_alloc(&nvbi, &src, w, h, 0, -1, NOUVEAU_BO_GART); - if (ret >= 0) - ret = nv_bo_alloc(&nvbo, &dst, w, h, tile_intel_y, -1, NOUVEAU_BO_GART); - if (ret < 0) - goto out; + nv_bo_alloc(&nvbi, &src, w, h, 0, -1, NOUVEAU_BO_GART); + nv_bo_alloc(&nvbo, &dst, w, h, tile_intel_y, -1, NOUVEAU_BO_GART); nouveau_bo_set_prime(nvbo, &prime_fd); @@ -691,34 +497,30 @@ static int test1_macro(void) memset(nvbo->map, 0xfc, w * h); if (pcopy) - ret = perform_copy(nvbo, &dst, 0, 0, nvbi, &src, 0, 0, w, h); + perform_copy(nvbo, &dst, 0, 0, nvbi, &src, 0, 0, w, h); else - ret = swtile_y(nvbo->map, nvbi->map, w, h); - if (!ret) - ret = check1_macro(nvbo->map, w/128, h/32); + swtile_y(nvbo->map, nvbi->map, w, h); + check1_macro(nvbo->map, w/128, h/32); -out: nouveau_bo_ref(NULL, &nvbo); nouveau_bo_ref(NULL, &nvbi); close(prime_fd); - return ret; } -static int dump_line(uint8_t *map) +static void dump_line(uint8_t *map) { uint32_t dx, dy; - fprintf(stderr, "Dumping sub-tile:\n"); + igt_debug("Dumping sub-tile:\n"); for (dy = 0; dy < 32; ++dy) { for (dx = 0; dx < 15; ++dx, ++map) { - fprintf(stderr, "%02x ", *map); + igt_debug("%02x ", *map); } - fprintf(stderr, "%02x\n", *(map++)); + igt_debug("%02x\n", *(map++)); } - return -1; } -static int check1_micro(void *map, uint32_t pitch, uint32_t lines, - uint32_t dst_x, uint32_t dst_y, uint32_t w, uint32_t h) +static void check1_micro(void *map, uint32_t pitch, uint32_t lines, + uint32_t dst_x, uint32_t dst_y, uint32_t w, uint32_t h) { uint32_t x, y; @@ -727,23 +529,22 @@ static int check1_micro(void *map, uint32_t pitch, uint32_t lines, for (y = 0; y < h; ++y, m += pitch) { for (x = 0; x < w; ++x) { uint8_t expected = ((y & 3) << 6) | (x & 0x3f); - if (expected != m[x]) { - fprintf(stderr, "failed check at x=%u y=%u, expected %02x got %02x\n", - x, y, expected, m[x]); - return dump_line(m); - } + + if (expected != m[x]) + dump_line(m); + + igt_assert_f(expected == m[x], + "failed check at x=%u y=%u, expected %02x got %02x\n", + x, y, expected, m[x]); } } - - return 0; } /* test 1, but check micro format, should be unaffected by bit9 swizzling */ -static int test1_micro(void) +static void test1_micro(void) { struct nouveau_bo *bo_intel = NULL, *bo_nvidia = NULL, *bo_linear = NULL; rect intel, nvidia, linear; - int ret = -1; uint32_t tiling = I915_TILING_Y; uint32_t src_x = 0, src_y = 0; @@ -754,31 +555,18 @@ static int test1_micro(void) int prime_fd; test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", w * h, 4096); - if (!test_intel_bo) - return -1; + igt_assert(test_intel_bo); drm_intel_bo_set_tiling(test_intel_bo, &tiling, w); - if (tiling != I915_TILING_Y) { - fprintf(stderr, "Couldn't set y tiling\n"); - goto out; - } - ret = drm_intel_gem_bo_map_gtt(test_intel_bo); - if (ret) - goto out; + igt_assert(tiling == I915_TILING_Y); + igt_assert(drm_intel_gem_bo_map_gtt(test_intel_bo) == 0); drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd); - if (prime_fd < 0) { - drm_intel_bo_unreference(test_intel_bo); - goto out; - } + igt_assert(prime_fd >= 0); noop_intel(test_intel_bo); - ret = nv_bo_alloc(&bo_intel, &intel, w, h, tile_intel_y, prime_fd, 0); - if (!ret) - ret = nv_bo_alloc(&bo_nvidia, &nvidia, w, h, 0x10, -1, NOUVEAU_BO_VRAM); - if (!ret) - ret = nv_bo_alloc(&bo_linear, &linear, w, h, 0, -1, NOUVEAU_BO_GART); - if (ret) - goto out; + nv_bo_alloc(&bo_intel, &intel, w, h, tile_intel_y, prime_fd, 0); + nv_bo_alloc(&bo_nvidia, &nvidia, w, h, 0x10, -1, NOUVEAU_BO_VRAM); + nv_bo_alloc(&bo_linear, &linear, w, h, 0, -1, NOUVEAU_BO_GART); for (y = 0; y < linear.h; ++y) { uint8_t *map = bo_linear->map; @@ -793,162 +581,21 @@ static int test1_micro(void) } } - ret = perform_copy(bo_nvidia, &nvidia, 0, 0, bo_linear, &linear, 0, 0, nvidia.pitch, nvidia.h); - if (ret) - goto out; + perform_copy(bo_nvidia, &nvidia, 0, 0, bo_linear, &linear, 0, 0, nvidia.pitch, nvidia.h); /* Perform the actual sub rectangle copy */ if (pcopy) - ret = perform_copy(bo_intel, &intel, dst_x, dst_y, bo_nvidia, &nvidia, src_x, src_y, w, h); + perform_copy(bo_intel, &intel, dst_x, dst_y, bo_nvidia, &nvidia, src_x, src_y, w, h); else - ret = swtile_y(test_intel_bo->virtual, bo_linear->map, w, h); - if (ret) - goto out; + swtile_y(test_intel_bo->virtual, bo_linear->map, w, h); noop_intel(test_intel_bo); - ret = check1_micro(test_intel_bo->virtual, intel.pitch, intel.h, dst_x, dst_y, w, h); + check1_micro(test_intel_bo->virtual, intel.pitch, intel.h, dst_x, dst_y, w, h); -out: nouveau_bo_ref(NULL, &bo_linear); nouveau_bo_ref(NULL, &bo_nvidia); nouveau_bo_ref(NULL, &bo_intel); drm_intel_bo_unreference(test_intel_bo); - return ret; -} - -static int check1_swizzle(uint32_t *p, uint32_t pitch, uint32_t lines, - uint32_t dst_x, uint32_t dst_y, uint32_t w, uint32_t h) -{ - uint32_t i, val, j; - - for (j = 0; j < 32; ++j, p += (pitch - w)/4) { - for (i = 0; i < 8; ++i, p += 4) { - val = (i * 32) + j; - val = (val) | (val << 8) | (val << 16) | (val << 24); - if (p[0] != val || p[1] != val || p[2] != val || p[3] != val) { - fprintf(stderr, "Retile check failed in first tile!\n"); - fprintf(stderr, "%08x %08x %08x %08x instead of %08x\n", - p[0], p[1], p[2], p[3], val); - return -1; - } - } - - val = 0x3e3e3e3e; - for (; i < w/16; ++i, p += 4) { - if (p[0] != val || p[1] != val || p[2] != val || p[3] != val) { - fprintf(stderr, "Retile check failed in second tile!\n"); - fprintf(stderr, "%08x %08x %08x %08x instead of %08x\n", - p[0], p[1], p[2], p[3], val); - return -1; - } - } - } - - for (j = 32; j < h; ++j, p += (pitch - w)/4) { - val = 0x7e7e7e7e; - for (i = 0; i < 8; ++i, p += 4) { - if (p[0] != val || p[1] != val || p[2] != val || p[3] != val) { - fprintf(stderr, "Retile check failed in third tile!\n"); - fprintf(stderr, "%08x %08x %08x %08x instead of %08x\n", - p[0], p[1], p[2], p[3], val); - return -1; - } - } - - val = 0xcececece; - for (; i < w/16; ++i, p += 4) { - if (p[0] != val || p[1] != val || p[2] != val || p[3] != val) { - fprintf(stderr, "Retile check failed in fourth tile!\n"); - fprintf(stderr, "%08x %08x %08x %08x instead of %08x\n", - p[0], p[1], p[2], p[3], val); - return -1; - } - } - } - return 0; -} - -/* Create a new bo, set tiling to y, and see if macro swizzling is done correctl */ -static int test1_swizzle(void) -{ - struct nouveau_bo *bo_intel = NULL, *bo_nvidia = NULL, *bo_linear = NULL; - rect intel, nvidia, linear; - int ret = -1; - uint32_t tiling = I915_TILING_Y; - - uint32_t src_x = 0, src_y = 0; - uint32_t dst_x = 0, dst_y = 0; - uint32_t x, y, w = 256, h = 64; - uint8_t *ptr; - - drm_intel_bo *test_intel_bo; - int prime_fd; - - test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", w * h, 4096); - if (!test_intel_bo) - return -1; - drm_intel_bo_set_tiling(test_intel_bo, &tiling, w); - if (tiling != I915_TILING_Y) { - fprintf(stderr, "Couldn't set y tiling\n"); - goto out; - } - ret = drm_intel_gem_bo_map_gtt(test_intel_bo); - if (ret) - goto out; - - drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd); - if (prime_fd < 0) { - drm_intel_bo_unreference(test_intel_bo); - goto out; - } - - ret = nv_bo_alloc(&bo_intel, &intel, w, h, tile_intel_y, prime_fd, 0); - if (!ret) - ret = nv_bo_alloc(&bo_nvidia, &nvidia, w, h, 0x10, -1, NOUVEAU_BO_VRAM); - if (!ret) - ret = nv_bo_alloc(&bo_linear, &linear, w, h, 0, -1, NOUVEAU_BO_GART); - if (ret) - goto out; - - noop_intel(test_intel_bo); - ptr = bo_linear->map; - for (x = 0; x < 128; x += 16) - for (y = 0; y < 32; ++y) - fill16(&ptr[y * w + x], x * 2 + y); - - /* second tile */ - for (x = 128; x < w; x += 16) - for (y = 0; y < 32; ++y) - fill16(&ptr[y * w + x], 0x3e); - - /* third tile */ - for (x = 0; x < 128; x += 16) - for (y = 32; y < h; ++y) - fill16(&ptr[y * w + x], 0x7e); - - /* last tile */ - for (x = 128; x < w; x += 16) - for (y = 32; y < h; ++y) - fill16(&ptr[y * w + x], 0xce); - - ret = perform_copy(bo_nvidia, &nvidia, 0, 0, bo_linear, &linear, 0, 0, nvidia.pitch, nvidia.h); - if (ret) - goto out; - - /* Perform the actual sub rectangle copy */ - ret = perform_copy(bo_intel, &intel, dst_x, dst_y, bo_nvidia, &nvidia, src_x, src_y, w, h); - if (ret) - goto out; - noop_intel(test_intel_bo); - - ret = check1_swizzle(test_intel_bo->virtual, intel.pitch, intel.h, dst_x, dst_y, w, h); - -out: - nouveau_bo_ref(NULL, &bo_linear); - nouveau_bo_ref(NULL, &bo_nvidia); - nouveau_bo_ref(NULL, &bo_intel); - drm_intel_bo_unreference(test_intel_bo); - return ret; } /* test 2, see if we can copy from linear to intel X format safely @@ -956,19 +603,15 @@ out: * as a reference for potential future tests. Software tiling is * used for now */ -static int test2(void) +static void test2(void) { - int ret; struct nouveau_bo *nvbo = NULL, *nvbi = NULL; rect dst, src; uint8_t *ptr; uint32_t w = 1024, h = 16, x, y; - ret = nv_bo_alloc(&nvbi, &src, w, h, 0, -1, NOUVEAU_BO_GART); - if (ret >= 0) - ret = nv_bo_alloc(&nvbo, &dst, w, h, tile_intel_x, -1, NOUVEAU_BO_GART); - if (ret < 0) - goto out; + nv_bo_alloc(&nvbi, &src, w, h, 0, -1, NOUVEAU_BO_GART); + nv_bo_alloc(&nvbo, &dst, w, h, tile_intel_x, -1, NOUVEAU_BO_GART); /* Set up something for our tile that should map into the first * y-major tile, assuming my understanding of documentation is @@ -998,31 +641,26 @@ static int test2(void) /* do this in software, there is no X major tiling in PCOPY (yet?) */ if (0 && pcopy) - ret = perform_copy(nvbo, &dst, 0, 0, nvbi, &src, 0, 0, w, h); + perform_copy(nvbo, &dst, 0, 0, nvbi, &src, 0, 0, w, h); else - ret = swtile_x(nvbo->map, nvbi->map, w, h); - if (!ret) - ret = check1_macro(nvbo->map, w/512, h/8); + swtile_x(nvbo->map, nvbi->map, w, h); + check1_macro(nvbo->map, w/512, h/8); -out: nouveau_bo_ref(NULL, &nvbo); nouveau_bo_ref(NULL, &nvbi); - return ret; } -static int check3(const uint32_t *p, uint32_t pitch, uint32_t lines, - uint32_t sub_x, uint32_t sub_y, - uint32_t sub_w, uint32_t sub_h) +static void check3(const uint32_t *p, uint32_t pitch, uint32_t lines, + uint32_t sub_x, uint32_t sub_y, + uint32_t sub_w, uint32_t sub_h) { uint32_t x, y; sub_w += sub_x; sub_h += sub_y; - if (p[pitch * lines / 4 - 1] == 0x03030303) { - fprintf(stderr, "copy failed: Not all lines have been copied back!\n"); - return -1; - } + igt_assert_f(p[pitch * lines / 4 - 1] != 0x03030303, + "copy failed: Not all lines have been copied back!\n"); for (y = 0; y < lines; ++y) { for (x = 0; x < pitch; x += 4, ++p) { @@ -1032,21 +670,18 @@ static int check3(const uint32_t *p, uint32_t pitch, uint32_t lines, expected = 0x80808080; else expected = 0x04040404; - if (*p != expected) { - fprintf(stderr, "%u,%u should be %08x, but is %08x\n", x, y, expected, *p); - return -1; - } + igt_assert_f(*p == expected, + "%u,%u should be %08x, but is %08x\n", + x, y, expected, *p); } } - return 0; } /* copy from nvidia bo to intel bo and copy to a linear bo to check if tiling went succesful */ -static int test3_base(int tile_src, int tile_dst) +static void test3_base(int tile_src, int tile_dst) { struct nouveau_bo *bo_intel = NULL, *bo_nvidia = NULL, *bo_linear = NULL; rect intel, nvidia, linear; - int ret; uint32_t cpp = 4; uint32_t src_x = 1 * cpp, src_y = 1; @@ -1057,87 +692,69 @@ static int test3_base(int tile_src, int tile_dst) int prime_fd; test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", 2048 * cpp * 768, 4096); - if (!test_intel_bo) - return -1; + igt_assert(test_intel_bo); drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd); - if (prime_fd < 0) { - drm_intel_bo_unreference(test_intel_bo); - return -1; - } + igt_assert(prime_fd >= 0); - ret = nv_bo_alloc(&bo_intel, &intel, 2048 * cpp, 768, tile_dst, prime_fd, 0); - if (!ret) - ret = nv_bo_alloc(&bo_nvidia, &nvidia, 300 * cpp, 300, tile_src, -1, NOUVEAU_BO_VRAM); - if (!ret) - ret = nv_bo_alloc(&bo_linear, &linear, 2048 * cpp, 768, 0, -1, NOUVEAU_BO_GART); - if (ret) - goto out; + nv_bo_alloc(&bo_intel, &intel, 2048 * cpp, 768, tile_dst, prime_fd, 0); + nv_bo_alloc(&bo_nvidia, &nvidia, 300 * cpp, 300, tile_src, -1, NOUVEAU_BO_VRAM); + nv_bo_alloc(&bo_linear, &linear, 2048 * cpp, 768, 0, -1, NOUVEAU_BO_GART); noop_intel(test_intel_bo); memset(bo_linear->map, 0x80, bo_linear->size); - ret = perform_copy(bo_intel, &intel, 0, 0, bo_linear, &linear, 0, 0, linear.pitch, linear.h); - if (ret) - goto out; + perform_copy(bo_intel, &intel, 0, 0, bo_linear, &linear, 0, 0, linear.pitch, linear.h); noop_intel(test_intel_bo); memset(bo_linear->map, 0x04, bo_linear->size); - ret = perform_copy(bo_nvidia, &nvidia, 0, 0, bo_linear, &linear, 0, 0, nvidia.pitch, nvidia.h); - if (ret) - goto out; + perform_copy(bo_nvidia, &nvidia, 0, 0, bo_linear, &linear, 0, 0, nvidia.pitch, nvidia.h); /* Perform the actual sub rectangle copy */ noop_intel(test_intel_bo); - ret = perform_copy(bo_intel, &intel, dst_x, dst_y, bo_nvidia, &nvidia, src_x, src_y, w, h); - if (ret) - goto out; + perform_copy(bo_intel, &intel, dst_x, dst_y, bo_nvidia, &nvidia, src_x, src_y, w, h); noop_intel(test_intel_bo); memset(bo_linear->map, 0x3, bo_linear->size); noop_intel(test_intel_bo); - ret = perform_copy(bo_linear, &linear, 0, 0, bo_intel, &intel, 0, 0, intel.pitch, intel.h); - if (ret) - goto out; + perform_copy(bo_linear, &linear, 0, 0, bo_intel, &intel, 0, 0, intel.pitch, intel.h); noop_intel(test_intel_bo); - ret = check3(bo_linear->map, linear.pitch, linear.h, dst_x, dst_y, w, h); + check3(bo_linear->map, linear.pitch, linear.h, dst_x, dst_y, w, h); -out: nouveau_bo_ref(NULL, &bo_linear); nouveau_bo_ref(NULL, &bo_nvidia); nouveau_bo_ref(NULL, &bo_intel); drm_intel_bo_unreference(test_intel_bo); - return ret; } -static int test3_1(void) +static void test3_1(void) { /* nvidia tiling to intel */ - return test3_base(0x40, tile_intel_y); + test3_base(0x40, tile_intel_y); } -static int test3_2(void) +static void test3_2(void) { /* intel tiling to nvidia */ - return test3_base(tile_intel_y, 0x40); + test3_base(tile_intel_y, 0x40); } -static int test3_3(void) +static void test3_3(void) { /* intel tiling to linear */ - return test3_base(tile_intel_y, 0); + test3_base(tile_intel_y, 0); } -static int test3_4(void) +static void test3_4(void) { /* linear tiling to intel */ - return test3_base(0, tile_intel_y); + test3_base(0, tile_intel_y); } -static int test3_5(void) +static void test3_5(void) { /* linear to linear */ - return test3_base(0, 0); + test3_base(0, 0); } /* Acquire when == SEQUENCE */ @@ -1151,44 +768,33 @@ static int test3_5(void) #define SEMA_ACQUIRE_GEQUAL 4 /* Test only new style semaphores, old ones are AWFUL */ -static int test_semaphore(void) +static void test_semaphore(void) { drm_intel_bo *test_intel_bo = NULL; struct nouveau_bo *sema_bo = NULL; - int ret = -1, prime_fd; + int prime_fd; uint32_t *sema; struct nouveau_pushbuf *push = npush; - if (ndev->chipset < 0x84) - return -1; + igt_skip_on(ndev->chipset < 0x84); /* Should probably be kept in sysmem */ test_intel_bo = drm_intel_bo_alloc(bufmgr, "semaphore bo", 4096, 4096); - if (!test_intel_bo) - goto out; + igt_assert(test_intel_bo); drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd); - if (prime_fd < 0) - goto out; - ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &sema_bo); + igt_assert(prime_fd >= 0); + igt_assert(nouveau_bo_prime_handle_ref(ndev, prime_fd, &sema_bo) == 0); close(prime_fd); - if (ret < 0) - goto out; - ret = drm_intel_gem_bo_map_gtt(test_intel_bo); - if (ret != 0) { - fprintf(stderr,"failed to map bo\n"); - goto out; - } + igt_assert(drm_intel_gem_bo_map_gtt(test_intel_bo) == 0); sema = test_intel_bo->virtual; sema++; *sema = 0; - ret = -1; - if (nouveau_pushbuf_space(push, 64, 0, 0) || - nouveau_pushbuf_refn(push, &(struct nouveau_pushbuf_refn) - { sema_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR }, 1)) - goto out; + igt_assert(nouveau_pushbuf_space(push, 64, 0, 0) == 0); + igt_assert(nouveau_pushbuf_refn(push, &(struct nouveau_pushbuf_refn) + { sema_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR }, 1) == 0); if (ndev->chipset < 0xc0) { struct nv04_fifo *nv04_fifo = nchannel->data; @@ -1227,80 +833,54 @@ static int test_semaphore(void) nouveau_pushbuf_kick(push, push->channel); usleep(1000); - if (*sema != 2) { - fprintf(stderr, "new sema should be 2 is %u\n", *sema); - goto out; - } + igt_assert(*sema == 2); *sema = 3; usleep(1000); - if (*sema != 4) { - fprintf(stderr, "new sema should be 4 is %u\n", *sema); - goto out; - } + igt_assert(*sema == 4); *sema = 5; usleep(1000); - if (*sema != 6) { - fprintf(stderr, "new sema should be 6 is %u\n", *sema); - goto out; - } + igt_assert(*sema == 6); *sema = 8; usleep(1000); - if (*sema != 9) { - fprintf(stderr, "new sema should be 9 is %u\n", *sema); - goto out; - } - ret = 0; + igt_assert(*sema == 9); -out: nouveau_bo_ref(NULL, &sema_bo); - if (test_intel_bo) - drm_intel_bo_unreference(test_intel_bo); - return ret; + drm_intel_bo_unreference(test_intel_bo); } -int main(int argc, char **argv) +igt_main { - int ret, failed = 0, run = 0; + igt_fixture { + find_and_open_devices(); - ret = find_and_open_devices(); - if (ret < 0) - return ret; + igt_require(nouveau_fd != -1); + igt_require(intel_fd != -1); - if (nouveau_fd == -1 || intel_fd == -1) { - fprintf(stderr,"failed to find intel and nouveau GPU\n"); - return 77; + /* set up intel bufmgr */ + bufmgr = drm_intel_bufmgr_gem_init(intel_fd, 4096); + igt_assert(bufmgr); + /* Do not enable reuse, we share (almost) all buffers. */ + //drm_intel_bufmgr_gem_enable_reuse(bufmgr); + + /* set up nouveau bufmgr */ + init_nouveau(); + + /* set up an intel batch buffer */ + devid = intel_get_drm_devid(intel_fd); + batch = intel_batchbuffer_alloc(bufmgr, devid); + igt_assert(batch); } - /* set up intel bufmgr */ - bufmgr = drm_intel_bufmgr_gem_init(intel_fd, 4096); - if (!bufmgr) - return -1; - /* Do not enable reuse, we share (almost) all buffers. */ - //drm_intel_bufmgr_gem_enable_reuse(bufmgr); - - /* set up nouveau bufmgr */ - ret = init_nouveau(); - if (ret < 0) - return 77; - - /* set up an intel batch buffer */ - devid = intel_get_drm_devid(intel_fd); - batch = intel_batchbuffer_alloc(bufmgr, devid); - -#define xtest(x, args...) do { \ - ret = ((x)(args)); \ - ++run; \ - if (ret) { \ - ++failed; \ - fprintf(stderr, "prime_pcopy: failed " #x "\n"); } \ - } while (0) +#define xtest(x, args...) \ + igt_subtest( #x ) \ + (x)(args); xtest(test1_macro); xtest(test1_micro); - xtest(test1_swizzle); + //xtest(test1_swizzle); xtest(test2); xtest(test3_1); xtest(test3_2); @@ -1309,21 +889,20 @@ int main(int argc, char **argv) xtest(test3_5); xtest(test_semaphore); - nouveau_bo_ref(NULL, &query_bo); - nouveau_object_del(&pcopy); - nouveau_bufctx_del(&nbufctx); - nouveau_pushbuf_del(&npush); - nouveau_object_del(&nchannel); + igt_fixture { + nouveau_bo_ref(NULL, &query_bo); + nouveau_object_del(&pcopy); + nouveau_bufctx_del(&nbufctx); + nouveau_pushbuf_del(&npush); + nouveau_object_del(&nchannel); - intel_batchbuffer_free(batch); + intel_batchbuffer_free(batch); - nouveau_client_del(&nclient); - nouveau_device_del(&ndev); - drm_intel_bufmgr_destroy(bufmgr); + nouveau_client_del(&nclient); + nouveau_device_del(&ndev); + drm_intel_bufmgr_destroy(bufmgr); - close(intel_fd); - close(nouveau_fd); - - printf("Tests: %u run, %u failed\n", run, failed); - return failed; + close(intel_fd); + close(nouveau_fd); + } } diff --git a/tests/prime_nv_test.c b/tests/prime_nv_test.c index 2269f84f..8211cd6f 100644 --- a/tests/prime_nv_test.c +++ b/tests/prime_nv_test.c @@ -22,11 +22,13 @@ #include <sys/stat.h> #include <sys/ioctl.h> -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "intel_bufmgr.h" #include "nouveau.h" -#include "intel_gpu_tools.h" +#include "intel_io.h" #include "intel_batchbuffer.h" +#include "intel_chipset.h" +#include "drmtest.h" int intel_fd = -1, nouveau_fd = -1; drm_intel_bufmgr *bufmgr; @@ -46,6 +48,8 @@ static int find_and_open_devices(void) char vendor_id[8]; int venid; for (i = 0; i < 9; i++) { + char *ret; + sprintf(path, "/sys/class/drm/card%d/device/vendor", i); if (stat(path, &buf)) break; @@ -54,7 +58,8 @@ static int find_and_open_devices(void) if (!fl) break; - fgets(vendor_id, 8, fl); + ret = fgets(vendor_id, 8, fl); + igt_assert(ret); fclose(fl); venid = strtoul(vendor_id, NULL, 16); @@ -80,25 +85,22 @@ static int find_and_open_devices(void) * close prime_fd, * unref buffers */ -static int test1(void) +static void test_i915_nv_sharing(void) { - int ret; drm_intel_bo *test_intel_bo; int prime_fd; struct nouveau_bo *nvbo; test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096); + igt_assert(test_intel_bo); drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd); - ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo); + igt_assert(nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo) == 0); close(prime_fd); - if (ret < 0) - return ret; nouveau_bo_ref(NULL, &nvbo); drm_intel_bo_unreference(test_intel_bo); - return 0; } /* @@ -109,38 +111,30 @@ static int test1(void) * close prime_fd, * unref buffers */ -static int test2(void) +static void test_nv_i915_sharing(void) { - int ret; drm_intel_bo *test_intel_bo; int prime_fd; struct nouveau_bo *nvbo; - ret = nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, - 0, BO_SIZE, NULL, &nvbo); - if (ret < 0) - return ret; - ret = nouveau_bo_set_prime(nvbo, &prime_fd); - if (ret < 0) - return ret; + igt_assert(nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, + 0, BO_SIZE, NULL, &nvbo) == 0); + igt_assert(nouveau_bo_set_prime(nvbo, &prime_fd) == 0); test_intel_bo = drm_intel_bo_gem_create_from_prime(bufmgr, prime_fd, BO_SIZE); close(prime_fd); - if (!test_intel_bo) - return -1; + igt_assert(test_intel_bo); nouveau_bo_ref(NULL, &nvbo); drm_intel_bo_unreference(test_intel_bo); - return 0; } /* * allocate intel, give to nouveau, map on nouveau * write 0xdeadbeef, non-gtt map on intel, read */ -static int test3(void) +static void test_nv_write_i915_cpu_mmap_read(void) { - int ret; drm_intel_bo *test_intel_bo; int prime_fd; struct nouveau_bo *nvbo = NULL; @@ -150,46 +144,28 @@ static int test3(void) drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd); - ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo); - if (ret < 0) { - fprintf(stderr,"failed to ref prime buffer %d\n", ret); - close(prime_fd); - goto free_intel; - } + igt_assert(nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo) == 0); close(prime_fd); - goto free_intel; - - ret = nouveau_bo_map(nvbo, NOUVEAU_BO_RDWR, nclient); - if (ret < 0) { - fprintf(stderr,"failed to map nouveau bo\n"); - goto out; - } + igt_assert(nouveau_bo_map(nvbo, NOUVEAU_BO_RDWR, nclient) == 0); ptr = nvbo->map; *ptr = 0xdeadbeef; drm_intel_bo_map(test_intel_bo, 1); - ptr = test_intel_bo->virtual; + igt_assert(ptr); - if (*ptr != 0xdeadbeef) { - fprintf(stderr,"mapped value doesn't match\n"); - ret = -1; - } -out: + igt_assert(*ptr == 0xdeadbeef); nouveau_bo_ref(NULL, &nvbo); -free_intel: drm_intel_bo_unreference(test_intel_bo); - return ret; } /* * allocate intel, give to nouveau, map on nouveau * write 0xdeadbeef, gtt map on intel, read */ -static int test4(void) +static void test_nv_write_i915_gtt_mmap_read(void) { - int ret; drm_intel_bo *test_intel_bo; int prime_fd; struct nouveau_bo *nvbo = NULL; @@ -199,227 +175,118 @@ static int test4(void) drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd); - ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo); + igt_assert(nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo) == 0); close(prime_fd); - if (ret < 0) { - fprintf(stderr,"failed to ref prime buffer\n"); - return ret; - } - - ret = nouveau_bo_map(nvbo, NOUVEAU_BO_RDWR, nclient); - if (ret < 0) { - fprintf(stderr,"failed to map nouveau bo\n"); - goto out; - } - - + igt_assert(nouveau_bo_map(nvbo, NOUVEAU_BO_RDWR, nclient) == 0); ptr = nvbo->map; *ptr = 0xdeadbeef; drm_intel_gem_bo_map_gtt(test_intel_bo); ptr = test_intel_bo->virtual; + igt_assert(ptr); + + igt_assert(*ptr == 0xdeadbeef); - if (*ptr != 0xdeadbeef) { - fprintf(stderr,"mapped value doesn't match\n"); - ret = -1; - } -out: nouveau_bo_ref(NULL, &nvbo); drm_intel_bo_unreference(test_intel_bo); - return ret; } /* test drm_intel_bo_map doesn't work properly, this tries to map the backing shmem fd, which doesn't exist for these objects */ -static int test5(void) +static void test_i915_import_cpu_mmap(void) { - int ret; drm_intel_bo *test_intel_bo; int prime_fd; struct nouveau_bo *nvbo; uint32_t *ptr; - ret = nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, - 0, BO_SIZE, NULL, &nvbo); - if (ret < 0) - return ret; - ret = nouveau_bo_set_prime(nvbo, &prime_fd); - if (ret < 0) - return ret; - + igt_assert(nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, + 0, BO_SIZE, NULL, &nvbo) == 0); + igt_assert(nouveau_bo_set_prime(nvbo, &prime_fd) == 0); test_intel_bo = drm_intel_bo_gem_create_from_prime(bufmgr, prime_fd, BO_SIZE); close(prime_fd); - if (!test_intel_bo) - return -1; + igt_assert(test_intel_bo); - ret = nouveau_bo_map(nvbo, NOUVEAU_BO_RDWR, nclient); - if (ret < 0) { - fprintf(stderr,"failed to map nouveau bo\n"); - goto out; - } + igt_assert(nouveau_bo_map(nvbo, NOUVEAU_BO_RDWR, nclient) == 0); ptr = nvbo->map; *ptr = 0xdeadbeef; - ret = drm_intel_bo_map(test_intel_bo, 0); - if (ret != 0) { - /* failed to map the bo is expected */ - ret = 0; - goto out; - } - if (!test_intel_bo->virtual) { - ret = 0; - goto out; - } + igt_assert(drm_intel_bo_map(test_intel_bo, 0) == 0); + igt_assert(test_intel_bo->virtual); ptr = test_intel_bo->virtual; - if (*ptr != 0xdeadbeef) { - fprintf(stderr,"mapped value doesn't match %08x\n", *ptr); - ret = -1; - } - out: + igt_assert(*ptr == 0xdeadbeef); nouveau_bo_ref(NULL, &nvbo); drm_intel_bo_unreference(test_intel_bo); - return ret; } /* test drm_intel_bo_map_gtt works properly, this tries to map the backing shmem fd, which doesn't exist for these objects */ -static int test6(void) +static void test_i915_import_gtt_mmap(void) { - int ret; drm_intel_bo *test_intel_bo; int prime_fd; struct nouveau_bo *nvbo; uint32_t *ptr; - ret = nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, - 0, BO_SIZE, NULL, &nvbo); - if (ret < 0) - return ret; - ret = nouveau_bo_set_prime(nvbo, &prime_fd); - if (ret < 0) - return ret; + igt_assert(nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, + 0, BO_SIZE, NULL, &nvbo) == 0); + igt_assert(nouveau_bo_set_prime(nvbo, &prime_fd) == 0); test_intel_bo = drm_intel_bo_gem_create_from_prime(bufmgr, prime_fd, BO_SIZE); close(prime_fd); - if (!test_intel_bo) - return -1; + igt_assert(test_intel_bo); - ret = nouveau_bo_map(nvbo, NOUVEAU_BO_RDWR, nclient); - if (ret < 0) { - fprintf(stderr,"failed to map nouveau bo\n"); - goto out; - } + igt_assert(nouveau_bo_map(nvbo, NOUVEAU_BO_RDWR, nclient) == 0); ptr = nvbo->map; *ptr = 0xdeadbeef; *(ptr + 1) = 0xa55a55; - ret = drm_intel_gem_bo_map_gtt(test_intel_bo); - if (ret != 0) { - fprintf(stderr,"failed to map bo\n"); - goto out; - } - if (!test_intel_bo->virtual) { - ret = -1; - fprintf(stderr,"failed to map bo\n"); - goto out; - } + igt_assert(drm_intel_gem_bo_map_gtt(test_intel_bo) == 0); + igt_assert(test_intel_bo->virtual); ptr = test_intel_bo->virtual; - if (*ptr != 0xdeadbeef) { - fprintf(stderr,"mapped value doesn't match %08x %08x\n", *ptr, *(ptr + 1)); - ret = -1; - } - out: + igt_assert(*ptr == 0xdeadbeef); nouveau_bo_ref(NULL, &nvbo); drm_intel_bo_unreference(test_intel_bo); - return ret; -} - -static int do_read(int fd, int handle, void *buf, int offset, int size) -{ - struct drm_i915_gem_pread intel_pread; - - /* Ensure that we don't have any convenient data in buf in case - * we fail. - */ - memset(buf, 0xd0, size); - - memset(&intel_pread, 0, sizeof(intel_pread)); - intel_pread.handle = handle; - intel_pread.data_ptr = (uintptr_t)buf; - intel_pread.size = size; - intel_pread.offset = offset; - - return ioctl(fd, DRM_IOCTL_I915_GEM_PREAD, &intel_pread); -} - -static int do_write(int fd, int handle, void *buf, int offset, int size) -{ - struct drm_i915_gem_pwrite intel_pwrite; - - memset(&intel_pwrite, 0, sizeof(intel_pwrite)); - intel_pwrite.handle = handle; - intel_pwrite.data_ptr = (uintptr_t)buf; - intel_pwrite.size = size; - intel_pwrite.offset = offset; - - return ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &intel_pwrite); } /* test 7 - import from nouveau into intel, test pread/pwrite fail */ -static int test7(void) +static void test_i915_import_pread_pwrite(void) { - int ret; drm_intel_bo *test_intel_bo; int prime_fd; struct nouveau_bo *nvbo; uint32_t *ptr; uint32_t buf[64]; - ret = nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, - 0, BO_SIZE, NULL, &nvbo); - if (ret < 0) - return ret; - ret = nouveau_bo_set_prime(nvbo, &prime_fd); - if (ret < 0) - return ret; + igt_assert(nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, + 0, BO_SIZE, NULL, &nvbo) == 0); + igt_assert(nouveau_bo_set_prime(nvbo, &prime_fd) == 0); test_intel_bo = drm_intel_bo_gem_create_from_prime(bufmgr, prime_fd, BO_SIZE); close(prime_fd); - if (!test_intel_bo) - return -1; + igt_assert(test_intel_bo); - ret = nouveau_bo_map(nvbo, NOUVEAU_BO_RDWR, nclient); - if (ret < 0) { - fprintf(stderr,"failed to map nouveau bo\n"); - goto out; - } + igt_assert(nouveau_bo_map(nvbo, NOUVEAU_BO_RDWR, nclient) == 0); ptr = nvbo->map; *ptr = 0xdeadbeef; - ret = do_read(intel_fd, test_intel_bo->handle, buf, 0, 256); - if (ret != -1) { - fprintf(stderr,"pread succeedded %d\n", ret); - goto out; - } + gem_read(intel_fd, test_intel_bo->handle, 0, buf, 256); + igt_assert(buf[0] == 0xdeadbeef); buf[0] = 0xabcdef55; - ret = do_write(intel_fd, test_intel_bo->handle, buf, 0, 4); - if (ret != -1) { - fprintf(stderr,"pwrite succeedded\n"); - goto out; - } - ret = 0; - out: + gem_write(intel_fd, test_intel_bo->handle, 0, buf, 4); + + igt_assert(*ptr == 0xabcdef55); + nouveau_bo_ref(NULL, &nvbo); drm_intel_bo_unreference(test_intel_bo); - return ret; } static void @@ -440,7 +307,7 @@ create_bo(drm_intel_bufmgr *ibufmgr, uint32_t val, int width, int height) drm_intel_bo *bo; bo = drm_intel_bo_alloc(ibufmgr, "bo", 4*width*height, 0); - assert(bo); + igt_assert(bo); /* gtt map doesn't have a write parameter, so just keep the mapping * around (to avoid the set_domain with the gtt write domain set) and @@ -454,9 +321,8 @@ create_bo(drm_intel_bufmgr *ibufmgr, uint32_t val, int width, int height) /* use intel hw to fill the BO with a blit from another BO, then readback from the nouveau bo, check value is correct */ -static int test8(void) +static void test_i915_blt_fill_nv_read(void) { - int ret; drm_intel_bo *test_intel_bo, *src_bo; int prime_fd; struct nouveau_bo *nvbo = NULL; @@ -468,115 +334,68 @@ static int test8(void) drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd); - ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo); + igt_assert(nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo) == 0); close(prime_fd); - if (ret < 0) { - fprintf(stderr,"failed to ref prime buffer\n"); - return ret; - } - intel_copy_bo(intel_batch, test_intel_bo, src_bo, 256, 1); + intel_copy_bo(intel_batch, test_intel_bo, src_bo, BO_SIZE); - ret = nouveau_bo_map(nvbo, NOUVEAU_BO_RDWR, nclient); - if (ret < 0) { - fprintf(stderr,"failed to map nouveau bo\n"); - goto out; - } + igt_assert(nouveau_bo_map(nvbo, NOUVEAU_BO_RDWR, nclient) == 0); drm_intel_bo_map(test_intel_bo, 0); ptr = nvbo->map; - if (*ptr != 0xaa55aa55) { - fprintf(stderr,"mapped value doesn't match\n"); - ret = -1; - } -out: + igt_assert(*ptr == 0xaa55aa55); nouveau_bo_ref(NULL, &nvbo); drm_intel_bo_unreference(test_intel_bo); - return ret; } /* test 8 use nouveau to do blit */ /* test 9 nouveau copy engine?? */ -int main(int argc, char **argv) +igt_main { - int ret; + igt_fixture { + igt_assert(find_and_open_devices() == 0); - ret = find_and_open_devices(); - if (ret < 0) - return ret; + igt_require(nouveau_fd != -1); + igt_require(intel_fd != -1); - if (nouveau_fd == -1 || intel_fd == -1) { - fprintf(stderr,"failed to find intel and nouveau GPU\n"); - return 77; - } + /* set up intel bufmgr */ + bufmgr = drm_intel_bufmgr_gem_init(intel_fd, 4096); + igt_assert(bufmgr); + /* Do not enable reuse, we share (almost) all buffers. */ + //drm_intel_bufmgr_gem_enable_reuse(bufmgr); - /* set up intel bufmgr */ - bufmgr = drm_intel_bufmgr_gem_init(intel_fd, 4096); - if (!bufmgr) - return -1; - /* Do not enable reuse, we share (almost) all buffers. */ - //drm_intel_bufmgr_gem_enable_reuse(bufmgr); - - /* set up nouveau bufmgr */ - ret = nouveau_device_wrap(nouveau_fd, 0, &ndev); - if (ret < 0) { - fprintf(stderr,"failed to wrap nouveau device\n"); - return 77; - } + /* set up nouveau bufmgr */ + igt_assert(nouveau_device_wrap(nouveau_fd, 0, &ndev) == 0); + igt_assert(nouveau_client_new(ndev, &nclient) == 0); - ret = nouveau_client_new(ndev, &nclient); - if (ret < 0) { - fprintf(stderr,"failed to setup nouveau client\n"); - return -1; + /* set up an intel batch buffer */ + devid = intel_get_drm_devid(intel_fd); + intel_batch = intel_batchbuffer_alloc(bufmgr, devid); } - /* set up an intel batch buffer */ - devid = intel_get_drm_devid(intel_fd); - intel_batch = intel_batchbuffer_alloc(bufmgr, devid); - - /* create an object on the i915 */ - ret = test1(); - if (ret) - fprintf(stderr,"prime_test: failed test 1\n"); - - ret = test2(); - if (ret) - fprintf(stderr,"prime_test: failed test 2\n"); - - ret = test3(); - if (ret) - fprintf(stderr,"prime_test: failed test 3\n"); +#define xtest(name) \ + igt_subtest(#name) \ + test_##name(); - ret = test4(); - if (ret) - fprintf(stderr,"prime_test: failed test 4\n"); + xtest(i915_nv_sharing); + xtest(nv_i915_sharing); + xtest(nv_write_i915_cpu_mmap_read); + xtest(nv_write_i915_gtt_mmap_read); + xtest(i915_import_cpu_mmap); + xtest(i915_import_gtt_mmap); + xtest(i915_import_pread_pwrite); + xtest(i915_blt_fill_nv_read); - ret = test5(); - if (ret) - fprintf(stderr,"prime_test: failed test 5\n"); + igt_fixture { + intel_batchbuffer_free(intel_batch); - ret = test6(); - if (ret) - fprintf(stderr,"prime_test: failed test 6\n"); + nouveau_device_del(&ndev); + drm_intel_bufmgr_destroy(bufmgr); - ret = test7(); - if (ret) - fprintf(stderr,"prime_test: failed test 7\n"); - - ret = test8(); - if (ret) - fprintf(stderr,"prime_test: failed test 8\n"); - - intel_batchbuffer_free(intel_batch); - - nouveau_device_del(&ndev); - drm_intel_bufmgr_destroy(bufmgr); - - close(intel_fd); - close(nouveau_fd); - - return ret; + close(intel_fd); + close(nouveau_fd); + } } diff --git a/tests/prime_self_import.c b/tests/prime_self_import.c index 111ed4da..67fd5217 100644 --- a/tests/prime_self_import.c +++ b/tests/prime_self_import.c @@ -1,5 +1,5 @@ /* - * Copyright © 2012 Intel Corporation + * Copyright © 2012-2013 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -31,51 +31,143 @@ * ... but with different fds, i.e. the wayland usecase. */ +#define _GNU_SOURCE #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <errno.h> #include <sys/stat.h> -#include <sys/mman.h> #include <sys/ioctl.h> +#include <pthread.h> + #include "drm.h" -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" +#include "igt_debugfs.h" #define BO_SIZE (16*1024) +static char counter; +volatile int pls_die = 0; + static void check_bo(int fd1, uint32_t handle1, int fd2, uint32_t handle2) { char *ptr1, *ptr2; - static char counter = 0; int i; ptr1 = gem_mmap(fd1, handle1, BO_SIZE, PROT_READ | PROT_WRITE); ptr2 = gem_mmap(fd2, handle2, BO_SIZE, PROT_READ | PROT_WRITE); - assert(ptr1); + igt_assert(ptr1); /* check whether it's still our old object first. */ for (i = 0; i < BO_SIZE; i++) { - assert(ptr1[i] == counter); - assert(ptr2[i] == counter); + igt_assert(ptr1[i] == counter); + igt_assert(ptr2[i] == counter); } counter++; memset(ptr1, counter, BO_SIZE); - assert(memcmp(ptr1, ptr2, BO_SIZE) == 0); + igt_assert(memcmp(ptr1, ptr2, BO_SIZE) == 0); munmap(ptr1, BO_SIZE); munmap(ptr2, BO_SIZE); } -int main(int argc, char **argv) +static void test_with_fd_dup(void) +{ + int fd1, fd2; + uint32_t handle, handle_import; + int dma_buf_fd1, dma_buf_fd2; + + counter = 0; + + fd1 = drm_open_any(); + fd2 = drm_open_any(); + + handle = gem_create(fd1, BO_SIZE); + + dma_buf_fd1 = prime_handle_to_fd(fd1, handle); + gem_close(fd1, handle); + + dma_buf_fd2 = dup(dma_buf_fd1); + close(dma_buf_fd1); + handle_import = prime_fd_to_handle(fd2, dma_buf_fd2); + check_bo(fd2, handle_import, fd2, handle_import); + + close(dma_buf_fd2); + check_bo(fd2, handle_import, fd2, handle_import); + + close(fd1); + close(fd2); +} + +static void test_with_two_bos(void) +{ + int fd1, fd2; + uint32_t handle1, handle2, handle_import; + int dma_buf_fd; + + counter = 0; + + fd1 = drm_open_any(); + fd2 = drm_open_any(); + + handle1 = gem_create(fd1, BO_SIZE); + handle2 = gem_create(fd1, BO_SIZE); + + dma_buf_fd = prime_handle_to_fd(fd1, handle1); + handle_import = prime_fd_to_handle(fd2, dma_buf_fd); + + close(dma_buf_fd); + gem_close(fd1, handle1); + + dma_buf_fd = prime_handle_to_fd(fd1, handle2); + handle_import = prime_fd_to_handle(fd2, dma_buf_fd); + check_bo(fd1, handle2, fd2, handle_import); + + gem_close(fd1, handle2); + close(dma_buf_fd); + + check_bo(fd2, handle_import, fd2, handle_import); + + close(fd1); + close(fd2); +} + +static void test_with_one_bo_two_files(void) +{ + int fd1, fd2; + uint32_t handle_import, handle_open, handle_orig, flink_name; + int dma_buf_fd1, dma_buf_fd2; + + fd1 = drm_open_any(); + fd2 = drm_open_any(); + + handle_orig = gem_create(fd1, BO_SIZE); + dma_buf_fd1 = prime_handle_to_fd(fd1, handle_orig); + + flink_name = gem_flink(fd1, handle_orig); + handle_open = gem_open(fd2, flink_name); + + dma_buf_fd2 = prime_handle_to_fd(fd2, handle_open); + handle_import = prime_fd_to_handle(fd2, dma_buf_fd2); + + /* dma-buf selfimporting an flink bo should give the same handle */ + igt_assert(handle_import == handle_open); + + close(fd1); + close(fd2); + close(dma_buf_fd1); + close(dma_buf_fd2); +} + +static void test_with_one_bo(void) { int fd1, fd2; uint32_t handle, handle_import1, handle_import2, handle_selfimport; @@ -94,11 +186,11 @@ int main(int argc, char **argv) /* reimport should give us the same handle so that userspace can check * whether it has that bo already somewhere. */ handle_import2 = prime_fd_to_handle(fd2, dma_buf_fd); - assert(handle_import1 == handle_import2); + igt_assert(handle_import1 == handle_import2); /* Same for re-importing on the exporting fd. */ handle_selfimport = prime_fd_to_handle(fd1, dma_buf_fd); - assert(handle == handle_selfimport); + igt_assert(handle == handle_selfimport); /* close dma_buf, check whether nothing disappears. */ close(dma_buf_fd); @@ -118,6 +210,250 @@ int main(int argc, char **argv) /* Completely rip out exporting fd. */ close(fd1); check_bo(fd2, handle_import1, fd2, handle_import1); +} + +static int get_object_count(void) +{ + FILE *file; + int ret, scanned; + int device = drm_get_card(); + char *path; + + igt_drop_caches_set(DROP_RETIRE); + + ret = asprintf(&path, "/sys/kernel/debug/dri/%d/i915_gem_objects", device); + igt_assert(ret != -1); + + file = fopen(path, "r"); + + scanned = fscanf(file, "%i objects", &ret); + igt_assert(scanned == 1); + + return ret; +} + +static void *thread_fn_reimport_vs_close(void *p) +{ + struct drm_gem_close close_bo; + int *fds = p; + int fd = fds[0]; + int dma_buf_fd = fds[1]; + uint32_t handle; + + while (!pls_die) { + handle = prime_fd_to_handle(fd, dma_buf_fd); + + close_bo.handle = handle; + ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close_bo); + } + + return (void *)0; +} + +static void test_reimport_close_race(void) +{ + pthread_t *threads; + int r, i, num_threads; + int fds[2]; + int obj_count; + void *status; + uint32_t handle; + int fake; + + /* Allocate exit handler fds in here so that we dont screw + * up the counts */ + fake = drm_open_any(); + + obj_count = get_object_count(); + + num_threads = sysconf(_SC_NPROCESSORS_ONLN); + + threads = calloc(num_threads, sizeof(pthread_t)); + + fds[0] = drm_open_any(); + igt_assert(fds[0] >= 0); - return 0; + handle = gem_create(fds[0], BO_SIZE); + + fds[1] = prime_handle_to_fd(fds[0], handle); + + for (i = 0; i < num_threads; i++) { + r = pthread_create(&threads[i], NULL, + thread_fn_reimport_vs_close, + (void *)(uintptr_t)fds); + igt_assert(r == 0); + } + + sleep(5); + + pls_die = 1; + + for (i = 0; i < num_threads; i++) { + pthread_join(threads[i], &status); + igt_assert(status == 0); + } + + close(fds[0]); + close(fds[1]); + + obj_count = get_object_count() - obj_count; + + igt_info("leaked %i objects\n", obj_count); + + close(fake); + + igt_assert(obj_count == 0); +} + +static void *thread_fn_export_vs_close(void *p) +{ + struct drm_prime_handle prime_h2f; + struct drm_gem_close close_bo; + int fd = (uintptr_t)p; + uint32_t handle; + + while (!pls_die) { + /* We want to race gem close against prime export on handle one.*/ + handle = gem_create(fd, 4096); + if (handle != 1) + gem_close(fd, handle); + + /* raw ioctl since we expect this to fail */ + + /* WTF: for gem_flink_race I've unconditionally used handle == 1 + * here, but with prime it seems to help a _lot_ to use + * something more random. */ + prime_h2f.handle = 1; + prime_h2f.flags = DRM_CLOEXEC; + prime_h2f.fd = -1; + + ioctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime_h2f); + + close_bo.handle = 1; + ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close_bo); + + close(prime_h2f.fd); + } + + return (void *)0; +} + +static void test_export_close_race(void) +{ + pthread_t *threads; + int r, i, num_threads; + int fd; + int obj_count; + void *status; + + obj_count = get_object_count(); + + num_threads = sysconf(_SC_NPROCESSORS_ONLN); + + threads = calloc(num_threads, sizeof(pthread_t)); + + fd = drm_open_any(); + igt_assert(fd >= 0); + + for (i = 0; i < num_threads; i++) { + r = pthread_create(&threads[i], NULL, + thread_fn_export_vs_close, + (void *)(uintptr_t)fd); + igt_assert(r == 0); + } + + sleep(5); + + pls_die = 1; + + for (i = 0; i < num_threads; i++) { + pthread_join(threads[i], &status); + igt_assert(status == 0); + } + + close(fd); + + obj_count = get_object_count() - obj_count; + + igt_info("leaked %i objects\n", obj_count); + igt_assert(obj_count == 0); +} + +static void test_llseek_size(void) +{ + int fd, i; + uint32_t handle; + int dma_buf_fd; + + counter = 0; + + fd = drm_open_any(); + + + for (i = 0; i < 10; i++) { + int bufsz = 4096 << i; + + handle = gem_create(fd, bufsz); + dma_buf_fd = prime_handle_to_fd(fd, handle); + + gem_close(fd, handle); + + igt_assert(prime_get_size(dma_buf_fd) == bufsz); + + close(dma_buf_fd); + } + + close(fd); +} + +static void test_llseek_bad(void) +{ + int fd; + uint32_t handle; + int dma_buf_fd; + + counter = 0; + + fd = drm_open_any(); + + + handle = gem_create(fd, BO_SIZE); + dma_buf_fd = prime_handle_to_fd(fd, handle); + + gem_close(fd, handle); + + igt_require(lseek(dma_buf_fd, 0, SEEK_END) >= 0); + + igt_assert(lseek(dma_buf_fd, -1, SEEK_END) == -1 && errno == EINVAL); + igt_assert(lseek(dma_buf_fd, 1, SEEK_SET) == -1 && errno == EINVAL); + igt_assert(lseek(dma_buf_fd, BO_SIZE, SEEK_SET) == -1 && errno == EINVAL); + igt_assert(lseek(dma_buf_fd, BO_SIZE + 1, SEEK_SET) == -1 && errno == EINVAL); + igt_assert(lseek(dma_buf_fd, BO_SIZE - 1, SEEK_SET) == -1 && errno == EINVAL); + + close(dma_buf_fd); + + close(fd); +} + +igt_main +{ + struct { + const char *name; + void (*fn)(void); + } tests[] = { + { "with_one_bo", test_with_one_bo }, + { "with_one_bo_two_files", test_with_one_bo_two_files }, + { "with_two_bos", test_with_two_bos }, + { "with_fd_dup", test_with_fd_dup }, + { "export-vs-gem_close-race", test_export_close_race }, + { "reimport-vs-gem_close-race", test_reimport_close_race }, + { "llseek-size", test_llseek_size }, + { "llseek-bad", test_llseek_bad }, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(tests); i++) { + igt_subtest(tests[i].name) + tests[i].fn(); + } } diff --git a/tests/prime_udl.c b/tests/prime_udl.c new file mode 100644 index 00000000..62b381a3 --- /dev/null +++ b/tests/prime_udl.c @@ -0,0 +1,180 @@ +/* basic set of prime tests between intel and nouveau */ + +/* test list - + 1. share buffer from intel -> nouveau. + 2. share buffer from nouveau -> intel + 3. share intel->nouveau, map on both, write intel, read nouveau + 4. share intel->nouveau, blit intel fill, readback on nouveau + test 1 + map buffer, read/write, map other size. + do some hw actions on the buffer + some illegal operations - + close prime fd try and map + + TODO add some nouveau rendering tests +*/ + + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <errno.h> + +#include "xf86drm.h" +#include <xf86drmMode.h> + +#include "ioctl_wrappers.h" +#include "intel_bufmgr.h" +#include "intel_io.h" +#include "intel_batchbuffer.h" +#include "drmtest.h" +#include "intel_chipset.h" + +int intel_fd = -1, udl_fd = -1; +drm_intel_bufmgr *bufmgr; +uint32_t devid; +struct intel_batchbuffer *intel_batch; + +#define BO_SIZE (640*480*2) + +static int find_and_open_devices(void) +{ + int i; + char path[80]; + struct stat buf; + FILE *fl; + char vendor_id[8]; + int venid; + for (i = 0; i < 9; i++) { + sprintf(path, "/sys/class/drm/card%d/device/vendor", i); + if (stat(path, &buf)) { + /* look for usb dev */ + sprintf(path, "/sys/class/drm/card%d/device/idVendor", i); + if (stat(path, &buf)) + break; + } + + fl = fopen(path, "r"); + if (!fl) + break; + + fgets(vendor_id, 8, fl); + fclose(fl); + + venid = strtoul(vendor_id, NULL, 16); + sprintf(path, "/dev/dri/card%d", i); + if (venid == 0x8086) { + intel_fd = open(path, O_RDWR); + if (!intel_fd) + return -1; + } else if (venid == 0x17e9) { + udl_fd = open(path, O_RDWR); + if (!udl_fd) + return -1; + } + } + return 0; +} + +static int dumb_bo_destroy(int fd, uint32_t handle) +{ + + struct drm_mode_destroy_dumb arg; + int ret; + memset(&arg, 0, sizeof(arg)); + arg.handle = handle; + ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg); + if (ret) + return -errno; + return 0; + +} + +/* + * simple share and import + */ +static int test1(void) +{ + drm_intel_bo *test_intel_bo; + int prime_fd; + int ret; + uint32_t udl_handle; + + test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096); + + drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd); + + ret = drmPrimeFDToHandle(udl_fd, prime_fd, &udl_handle); + + dumb_bo_destroy(udl_fd, udl_handle); + drm_intel_bo_unreference(test_intel_bo); + return ret; +} + +static int test2(void) +{ + drm_intel_bo *test_intel_bo; + uint32_t fb_id; + drmModeClip clip; + int prime_fd; + uint32_t udl_handle; + int ret; + + test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096); + + drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd); + + ret = drmPrimeFDToHandle(udl_fd, prime_fd, &udl_handle); + if (ret) + goto out; + + ret = drmModeAddFB(udl_fd, 640, 480, 16, 16, 640, udl_handle, &fb_id); + if (ret) + goto out; + + clip.x1 = 0; + clip.y1 = 0; + clip.x2 = 10; + clip.y2 = 10; + ret = drmModeDirtyFB(udl_fd, fb_id, &clip, 1); + if (ret) { + return ret; + } +out: + dumb_bo_destroy(udl_fd, udl_handle); + drm_intel_bo_unreference(test_intel_bo); + return ret; +} + +igt_simple_main +{ + igt_skip_on_simulation(); + + igt_assert(find_and_open_devices() >= 0); + + igt_skip_on(udl_fd == -1); + igt_skip_on(intel_fd == -1); + + /* set up intel bufmgr */ + bufmgr = drm_intel_bufmgr_gem_init(intel_fd, 4096); + drm_intel_bufmgr_gem_enable_reuse(bufmgr); + + /* set up an intel batch buffer */ + devid = intel_get_drm_devid(intel_fd); + intel_batch = intel_batchbuffer_alloc(bufmgr, devid); + + /* create an object on the i915 */ + igt_assert(test1() == 0); + + igt_assert(test2() == 0); + + intel_batchbuffer_free(intel_batch); + + drm_intel_bufmgr_destroy(bufmgr); + + close(intel_fd); + close(udl_fd); +} diff --git a/tests/sysfs_l3_parity b/tests/sysfs_l3_parity index 6f814a13..e9d44110 100755 --- a/tests/sysfs_l3_parity +++ b/tests/sysfs_l3_parity @@ -8,20 +8,20 @@ fi SOURCE_DIR="$( dirname "${BASH_SOURCE[0]}" )" . $SOURCE_DIR/drm_lib.sh -$SOURCE_DIR/../tools/intel_l3_parity -c +$SOURCE_DIR/../tools/intel_l3_parity -r 0 -b 0 -s 0 -e #Check that we can remap a row -$SOURCE_DIR/../tools/intel_l3_parity 0,0,0 -disabled=`$SOURCE_DIR/../tools/intel_l3_parity | grep -c 'Row 0, Bank 0, Subbank 0 is disabled'` +$SOURCE_DIR/../tools/intel_l3_parity -r 0 -b 0 -s 0 -d +disabled=`$SOURCE_DIR/../tools/intel_l3_parity -l | grep -c 'Row 0, Bank 0, Subbank 0 is disabled'` if [ "$disabled" != "1" ] ; then echo "Fail" exit 1 fi -$SOURCE_DIR/../tools/intel_l3_parity -c +$SOURCE_DIR/../tools/intel_l3_parity -r 0 -b 0 -s 0 -e #Check that we can clear remaps -if [ `$SOURCE_DIR/../tools/intel_l3_parity | wc -c` != "0" ] ; then - echo "Fail" +if [ `$SOURCE_DIR/../tools/intel_l3_parity -l | wc -l` != 1 ] ; then + echo "Fail 2" exit 1 fi diff --git a/tests/sysfs_rc6_residency.c b/tests/sysfs_rc6_residency.c deleted file mode 100644 index 2f33697a..00000000 --- a/tests/sysfs_rc6_residency.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright © 2012 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * Authors: - * Ben Widawsky <ben@bwidawsk.net> - * - */ - -#define _GNU_SOURCE -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include "drmtest.h" - -#define SLEEP_DURATION 3000 // in milliseconds -#define RC6_FUDGE 900 // in milliseconds - -static unsigned int readit(const char *path) -{ - unsigned int ret; - - FILE *file; - file = fopen(path, "r"); - if (file == NULL) { - fprintf(stderr, "Couldn't open %s (%d)\n", path, errno); - abort(); - } - fscanf(file, "%u", &ret); - fclose(file); - - return ret; -} - -int main(int argc, char *argv[]) -{ - const int device = drm_get_card(0); - char *path, *pathp, *pathpp; - int fd, ret; - unsigned int value1, value1p, value1pp, value2, value2p, value2pp; - FILE *file; - int diff; - - /* Use drm_open_any to verify device existence */ - fd = drm_open_any(); - close(fd); - - ret = asprintf(&path, "/sys/class/drm/card%d/power/rc6_enable", device); - assert(ret != -1); - - /* For some reason my ivb isn't idle even after syncing up with the gpu. - * Let's add a sleept just to make it happy. */ - sleep(5); - - file = fopen(path, "r"); - if (!file) { - printf("kernel too old or rc6 not supported on this platform.\n"); - exit(77); - } - - /* claim success if no rc6 enabled. */ - if (readit(path) == 0) - exit(EXIT_SUCCESS); - - ret = asprintf(&path, "/sys/class/drm/card%d/power/rc6_residency_ms", device); - assert(ret != -1); - ret = asprintf(&pathp, "/sys/class/drm/card%d/power/rc6p_residency_ms", device); - assert(ret != -1); - ret = asprintf(&pathpp, "/sys/class/drm/card%d/power/rc6pp_residency_ms", device); - assert(ret != -1); - - value1 = readit(path); - value1p = readit(pathp); - value1pp = readit(pathpp); - sleep(SLEEP_DURATION / 1000); - value2 = readit(path); - value2p = readit(pathp); - value2pp = readit(pathpp); - - free(pathpp); - free(pathp); - free(path); - - diff = (value2pp - value1pp) + - (value2p - value1p) + - (value2 - value1); - - if (diff > (SLEEP_DURATION + RC6_FUDGE)) { - fprintf(stderr, "Diff was too high. That is unpossible\n"); - exit(EXIT_FAILURE); - } - if (diff < (SLEEP_DURATION - RC6_FUDGE)) { - fprintf(stderr, "GPU was not in RC6 long enough. Check that " - "the GPU is as idle as possible (ie. no X, " - "running and running no other tests)\n"); - exit(EXIT_FAILURE); - } - - exit(EXIT_SUCCESS); -} diff --git a/tests/template.c b/tests/template.c new file mode 100644 index 00000000..24fd8506 --- /dev/null +++ b/tests/template.c @@ -0,0 +1,80 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * + */ + +#include "drmtest.h" + +/* + * Note that test function (and code called by them) should generally not return + * a variable indicating success/failure. Instead use the igt_require/igt_assert + * macros to skip out of the entire subtest. + * + * Also, helper functions should only return a status code if the callers have a + * real need to differentiate. If the only thing they do is call igt_assert or a + * similar macro then it'll result in simpler code when the check is moved + * completely into the helper. + */ +static void test_A(int fd) +{ +} + +static void test_B(int fd) +{ +} + +/* + * Variables which are written to in igt_fixtures/subtest blocks need to be + * allocated outside of the relevant function scope, otherwise gcc will wreak + * havoc (since these magic blocks use setjmp/longjmp internally). + * + * Common practice is to put variables used in the main test function into + * global scope, but only right above the main function itself (to avoid leaking + * it into other functions). + */ + +int drm_fd; + +igt_main +{ + igt_fixture { + drm_fd = drm_open_any(); + igt_require(drm_fd >= 0); + + /* Set up other interesting stuff shared by all tests. */ + } + + igt_subtest("A") + test_A(drm_fd); + igt_subtest("B") + test_B(drm_fd); + /* + * Note that subtest names can be programatically generated. See the + * various uses of igt_subtest_f for a few neat ideas. + */ + + igt_fixture { + close(drm_fd); + } +} diff --git a/tests/test_rte_check b/tests/test_rte_check new file mode 100755 index 00000000..6389592d --- /dev/null +++ b/tests/test_rte_check @@ -0,0 +1,8 @@ +#!/bin/bash + +whoami | grep root || ( echo ERROR: not running as root; exit 1 ) + +SOURCE_DIR="$( dirname "${BASH_SOURCE[0]}" )" +. $SOURCE_DIR/drm_lib.sh + +exit 0 diff --git a/tests/testdisplay.c b/tests/testdisplay.c index 14d7da39..125e7d2f 100644 --- a/tests/testdisplay.c +++ b/tests/testdisplay.c @@ -45,33 +45,44 @@ * - DP commands (e.g. poweroff) * - verify outputs against VBT/physical connectors */ +#ifdef HAVE_CONFIG_H #include "config.h" +#endif -#include <assert.h> #include <cairo.h> #include <errno.h> #include <math.h> #include <stdint.h> +#include <stdbool.h> +#include <strings.h> #include <unistd.h> +#include <termios.h> #include <sys/poll.h> #include <sys/time.h> -#include <sys/mman.h> #include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> -#include "i915_drm.h" +#include "ioctl_wrappers.h" #include "drmtest.h" #include "testdisplay.h" +#include "igt_kms.h" #include <stdlib.h> #include <signal.h> +static int tio_fd; +struct termios saved_tio; + drmModeRes *resources; int drm_fd, modes; -int dump_info = 0, test_all_modes =0, test_preferred_mode = 0, force_mode = 0, - test_plane, enable_tiling; +int test_all_modes = 0, test_preferred_mode = 0, force_mode = 0, test_plane, + test_stereo_modes, enable_tiling; int sleep_between_modes = 5; +int do_dpms = 0; /* This aliases to DPMS_ON */ uint32_t depth = 24, stride, bpp; int qr_code = 0; +int specified_mode_num = -1, specified_disp_id = -1; drmModeModeInfo force_timing; @@ -81,62 +92,6 @@ unsigned int plane_crtc_id; unsigned int plane_id; int plane_width, plane_height; static const uint32_t SPRITE_COLOR_KEY = 0x00aaaaaa; -uint32_t *fb_ptr; - -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) - -struct type_name { - int type; - const char *name; -}; - -#define type_name_fn(res) \ -static const char * res##_str(int type) { \ - unsigned int i; \ - for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \ - if (res##_names[i].type == type) \ - return res##_names[i].name; \ - } \ - return "(invalid)"; \ -} - -struct type_name encoder_type_names[] = { - { DRM_MODE_ENCODER_NONE, "none" }, - { DRM_MODE_ENCODER_DAC, "DAC" }, - { DRM_MODE_ENCODER_TMDS, "TMDS" }, - { DRM_MODE_ENCODER_LVDS, "LVDS" }, - { DRM_MODE_ENCODER_TVDAC, "TVDAC" }, -}; - -type_name_fn(encoder_type) - -struct type_name connector_status_names[] = { - { DRM_MODE_CONNECTED, "connected" }, - { DRM_MODE_DISCONNECTED, "disconnected" }, - { DRM_MODE_UNKNOWNCONNECTION, "unknown" }, -}; - -type_name_fn(connector_status) - -struct type_name connector_type_names[] = { - { DRM_MODE_CONNECTOR_Unknown, "unknown" }, - { DRM_MODE_CONNECTOR_VGA, "VGA" }, - { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, - { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, - { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, - { DRM_MODE_CONNECTOR_Composite, "composite" }, - { DRM_MODE_CONNECTOR_SVIDEO, "s-video" }, - { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, - { DRM_MODE_CONNECTOR_Component, "component" }, - { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" }, - { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort" }, - { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" }, - { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" }, - { DRM_MODE_CONNECTOR_TV, "TV" }, - { DRM_MODE_CONNECTOR_eDP, "Embedded DisplayPort" }, -}; - -type_name_fn(connector_type) /* * Mode setting with the kernel interfaces is a bit of a chore. @@ -152,6 +107,7 @@ struct connector { drmModeEncoder *encoder; drmModeConnector *connector; int crtc; + int crtc_idx; int pipe; }; @@ -182,8 +138,8 @@ static void dump_connectors_fd(int drmfd) printf("%d\t%d\t%s\t%s\t%dx%d\t\t%d\n", connector->connector_id, connector->encoder_id, - connector_status_str(connector->connection), - connector_type_str(connector->connector_type), + kmstest_connector_status_str(connector->connection), + kmstest_connector_type_str(connector->connector_type), connector->mmWidth, connector->mmHeight, connector->count_modes); @@ -193,8 +149,10 @@ static void dump_connectors_fd(int drmfd) printf(" modes:\n"); printf(" name refresh (Hz) hdisp hss hse htot vdisp " "vss vse vtot flags type clock\n"); - for (j = 0; j < connector->count_modes; j++) + for (j = 0; j < connector->count_modes; j++){ + fprintf(stdout, "[%d]", j ); kmstest_dump_mode(&connector->modes[j]); + } drmModeFreeConnector(connector); } @@ -233,109 +191,58 @@ static void dump_crtcs_fd(int drmfd) drmModeFreeResources(mode_resources); } -static void connector_find_preferred_mode(struct connector *c) +static void dump_info(void) { - drmModeConnector *connector; - drmModeEncoder *encoder = NULL; - int i, j; - - /* First, find the connector & mode */ - c->mode_valid = 0; - connector = drmModeGetConnector(drm_fd, c->id); - if (!connector) { - fprintf(stderr, "could not get connector %d: %s\n", - c->id, strerror(errno)); - drmModeFreeConnector(connector); - return; - } - - if (connector->connection != DRM_MODE_CONNECTED) { - drmModeFreeConnector(connector); - return; - } - - if (!connector->count_modes) { - fprintf(stderr, "connector %d has no modes\n", c->id); - drmModeFreeConnector(connector); - return; - } - - if (connector->connector_id != c->id) { - fprintf(stderr, "connector id doesn't match (%d != %d)\n", - connector->connector_id, c->id); - drmModeFreeConnector(connector); - return; - } - - for (j = 0; j < connector->count_modes; j++) { - c->mode = connector->modes[j]; - if (c->mode.type & DRM_MODE_TYPE_PREFERRED) { - c->mode_valid = 1; - break; - } - } - - if (!c->mode_valid) { - if (connector->count_modes > 0) { - /* use the first mode as test mode */ - c->mode = connector->modes[0]; - c->mode_valid = 1; - } - else { - fprintf(stderr, "failed to find any modes on connector %d\n", - c->id); - return; - } - } - - /* Now get the encoder */ - for (i = 0; i < connector->count_encoders; i++) { - encoder = drmModeGetEncoder(drm_fd, connector->encoders[i]); - - if (!encoder) { - fprintf(stderr, "could not get encoder %i: %s\n", - resources->encoders[i], strerror(errno)); - drmModeFreeEncoder(encoder); - continue; - } - - break; - } + dump_connectors_fd(drm_fd); + dump_crtcs_fd(drm_fd); +} - c->encoder = encoder; +static void connector_find_preferred_mode(uint32_t connector_id, + unsigned long crtc_idx_mask, + int mode_num, struct connector *c) +{ + struct kmstest_connector_config config; - if (i == resources->count_encoders) { - fprintf(stderr, "failed to find encoder\n"); + if (kmstest_get_connector_config(drm_fd, connector_id, crtc_idx_mask, + &config) < 0) { c->mode_valid = 0; return; } - /* Find first CRTC not in use */ - for (i = 0; i < resources->count_crtcs; i++) { - if (resources->crtcs[i] && (c->encoder->possible_crtcs & (1<<i))) - break; + c->connector = config.connector; + c->encoder = config.encoder; + c->crtc = config.crtc->crtc_id; + c->crtc_idx = config.crtc_idx; + c->pipe = config.pipe; + + if (mode_num != -1) { + igt_assert(mode_num < config.connector->count_modes); + c->mode = config.connector->modes[mode_num]; + } else { + c->mode = config.default_mode; } - c->crtc = resources->crtcs[i]; - c->pipe = i; - - if(test_preferred_mode || force_mode) - resources->crtcs[i] = 0; - - c->connector = connector; + c->mode_valid = 1; } static void -paint_color_key(void) +paint_color_key(struct igt_fb *fb_info) { int i, j; + uint32_t *fb_ptr; + + fb_ptr = gem_mmap(drm_fd, fb_info->gem_handle, + fb_info->size, PROT_READ | PROT_WRITE); + igt_assert(fb_ptr); for (i = crtc_y; i < crtc_y + crtc_h; i++) for (j = crtc_x; j < crtc_x + crtc_w; j++) { uint32_t offset; - offset = (i * width) + j; + offset = (i * fb_info->stride / 4) + j; fb_ptr[offset] = SPRITE_COLOR_KEY; } + + munmap(fb_ptr, fb_info->size); } static void paint_image(cairo_t *cr, const char *file) @@ -369,94 +276,58 @@ static void paint_image(cairo_t *cr, const char *file) cairo_surface_destroy(image); } -static void -paint_output_info(cairo_t *cr, int l_width, int l_height, void *priv) +static void paint_output_info(struct connector *c, struct igt_fb *fb) { - struct connector *c = priv; - cairo_text_extents_t name_extents, mode_extents; - char name_buf[128], mode_buf[128]; - int i, x, y, modes_x, modes_y; - - /* Get text extents for each string */ - snprintf(name_buf, sizeof name_buf, "%s", - connector_type_str(c->connector->connector_type)); - cairo_set_font_size(cr, 48); - cairo_select_font_face(cr, "Helvetica", - CAIRO_FONT_SLANT_NORMAL, - CAIRO_FONT_WEIGHT_NORMAL); - cairo_text_extents(cr, name_buf, &name_extents); - - snprintf(mode_buf, sizeof mode_buf, "%s @ %dHz on %s encoder", - c->mode.name, c->mode.vrefresh, - encoder_type_str(c->encoder->encoder_type)); - cairo_set_font_size(cr, 36); - cairo_text_extents(cr, mode_buf, &mode_extents); + cairo_t *cr = igt_get_cairo_ctx(drm_fd, fb); + int l_width = fb->width; + int l_height = fb->height; + double str_width; + double x, y, top_y; + double max_width; + int i; + + igt_paint_test_pattern(cr, l_width, l_height); - /* Paint output name */ - x = l_width / 2; - x -= name_extents.width / 2; - y = l_height / 2; - y -= (name_extents.height / 2) - (mode_extents.height / 2) - 10; + cairo_move_to(cr, l_width / 2, l_height / 2); + + /* Print connector and mode name */ cairo_set_font_size(cr, 48); - cairo_move_to(cr, x, y); - cairo_text_path(cr, name_buf); - cairo_set_source_rgb(cr, 0, 0, 0); - cairo_stroke_preserve(cr); - cairo_set_source_rgb(cr, 1, 1, 1); - cairo_fill(cr); - - /* Paint mode name */ - x = l_width / 2; - x -= mode_extents.width / 2; - modes_x = x; - y = l_height / 2; - y += (mode_extents.height / 2) + (name_extents.height / 2) + 10; + igt_cairo_printf_line(cr, align_hcenter, 10, "%s", + kmstest_connector_type_str(c->connector->connector_type)); + cairo_set_font_size(cr, 36); - cairo_move_to(cr, x, y); - cairo_text_path(cr, mode_buf); - cairo_set_source_rgb(cr, 0, 0, 0); - cairo_stroke_preserve(cr); - cairo_set_source_rgb(cr, 1, 1, 1); - cairo_fill(cr); + str_width = igt_cairo_printf_line(cr, align_hcenter, 10, + "%s @ %dHz on %s encoder", c->mode.name, c->mode.vrefresh, + kmstest_encoder_type_str(c->encoder->encoder_type)); + + cairo_rel_move_to(cr, -str_width / 2, 0); /* List available modes */ - snprintf(mode_buf, sizeof mode_buf, "Available modes:"); cairo_set_font_size(cr, 18); - cairo_text_extents(cr, mode_buf, &mode_extents); - x = modes_x; - modes_x = x + mode_extents.width; - y += mode_extents.height + 10; - modes_y = y; - cairo_move_to(cr, x, y); - cairo_text_path(cr, mode_buf); - cairo_set_source_rgb(cr, 0, 0, 0); - cairo_stroke_preserve(cr); - cairo_set_source_rgb(cr, 1, 1, 1); - cairo_fill(cr); + str_width = igt_cairo_printf_line(cr, align_left, 10, + "Available modes:"); + cairo_rel_move_to(cr, str_width, 0); + cairo_get_current_point(cr, &x, &top_y); + max_width = 0; for (i = 0; i < c->connector->count_modes; i++) { - snprintf(mode_buf, sizeof mode_buf, "%s @ %dHz", - c->connector->modes[i].name, - c->connector->modes[i].vrefresh); - cairo_set_font_size(cr, 18); - cairo_text_extents(cr, mode_buf, &mode_extents); - x = modes_x - mode_extents.width; /* right justify modes */ - y += mode_extents.height + 10; - if (y + mode_extents.height >= height) { - y = modes_y + mode_extents.height + 10; - modes_x += mode_extents.width + 10; - x = modes_x - mode_extents.width; + cairo_get_current_point(cr, &x, &y); + if (y >= l_height) { + x += max_width + 10; + max_width = 0; + cairo_move_to(cr, x, top_y); } - cairo_move_to(cr, x, y); - cairo_text_path(cr, mode_buf); - cairo_set_source_rgb(cr, 0, 0, 0); - cairo_stroke_preserve(cr); - cairo_set_source_rgb(cr, 1, 1, 1); - cairo_fill(cr); + str_width = igt_cairo_printf_line(cr, align_right, 10, + "%s @ %dHz", c->connector->modes[i].name, + c->connector->modes[i].vrefresh); + if (str_width > max_width) + max_width = str_width; } if (qr_code) - paint_image(cr, "./pass.png"); + paint_image(cr, IGT_DATADIR"/pass.png"); + + igt_assert(!cairo_status(cr)); } static void sighandler(int signo) @@ -480,18 +351,8 @@ static void set_mode(struct connector *c) { unsigned int fb_id = 0; - int j, test_mode_num; - - if (depth <= 8) - bpp = 8; - else if (depth > 8 && depth <= 16) - bpp = 16; - else if (depth > 16 && depth <= 32) - bpp = 32; - - connector_find_preferred_mode(c); - if (!c->mode_valid) - return; + struct igt_fb fb_info[2] = { }; + int j, test_mode_num, current_fb = 0, old_fb = -1; test_mode_num = 1; if (force_mode){ @@ -503,29 +364,27 @@ set_mode(struct connector *c) test_mode_num = c->connector->count_modes; for (j = 0; j < test_mode_num; j++) { - struct kmstest_fb fb_info; if (test_all_modes) c->mode = c->connector->modes[j]; + /* set_mode() only tests 2D modes */ + if (c->mode.flags & DRM_MODE_FLAG_3D_MASK) + continue; + if (!c->mode_valid) continue; width = c->mode.hdisplay; height = c->mode.vdisplay; - fb_id = kmstest_create_fb(drm_fd, width, height, bpp, depth, - enable_tiling, &fb_info, - paint_output_info, c); - - fb_ptr = gem_mmap(drm_fd, fb_info.gem_handle, - fb_info.size, PROT_READ | PROT_WRITE); - assert(fb_ptr); - paint_color_key(); - - gem_close(drm_fd, fb_info.gem_handle); + fb_id = igt_create_fb(drm_fd, width, height, + igt_bpp_depth_to_drm_format(bpp, depth), + enable_tiling, &fb_info[current_fb]); + paint_output_info(c, &fb_info[current_fb]); + paint_color_key(&fb_info[current_fb]); - fprintf(stdout, "CRTS(%u):",c->crtc); + fprintf(stdout, "CRTC(%u):[%d]",c->crtc, j); kmstest_dump_mode(&c->mode); if (drmModeSetCrtc(drm_fd, c->crtc, fb_id, 0, 0, &c->id, 1, &c->mode)) { @@ -535,19 +394,197 @@ set_mode(struct connector *c) continue; } + if (old_fb != -1) + igt_remove_fb(drm_fd, &fb_info[old_fb]); + old_fb = current_fb; + current_fb = 1 - current_fb; + if (sleep_between_modes && test_all_modes && !qr_code) sleep(sleep_between_modes); + if (do_dpms) { + kmstest_set_connector_dpms(drm_fd, c->connector, do_dpms); + sleep(sleep_between_modes); + kmstest_set_connector_dpms(drm_fd, c->connector, DRM_MODE_DPMS_ON); + } + if (qr_code){ set_single(); pause(); } + } + if (test_all_modes) + igt_remove_fb(drm_fd, &fb_info[old_fb]); + + drmModeFreeEncoder(c->encoder); + drmModeFreeConnector(c->connector); +} + +struct box { + int x, y, width, height; +}; + +struct stereo_fb_layout { + int fb_width, fb_height; + struct box left, right; +}; + +static void box_init(struct box *box, int x, int y, int bwidth, int bheight) +{ + box->x = x; + box->y = y; + box->width = bwidth; + box->height = bheight; +} + +static void stereo_fb_layout_from_mode(struct stereo_fb_layout *layout, + drmModeModeInfo *mode) +{ + unsigned int format = mode->flags & DRM_MODE_FLAG_3D_MASK; + const int hdisplay = mode->hdisplay, vdisplay = mode->vdisplay; + int middle; + + switch (format) { + case DRM_MODE_FLAG_3D_TOP_AND_BOTTOM: + layout->fb_width = hdisplay; + layout->fb_height = vdisplay; + + middle = vdisplay / 2; + box_init(&layout->left, 0, 0, hdisplay, middle); + box_init(&layout->right, + 0, middle, hdisplay, vdisplay - middle); + break; + case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF: + layout->fb_width = hdisplay; + layout->fb_height = vdisplay; + + middle = hdisplay / 2; + box_init(&layout->left, 0, 0, middle, vdisplay); + box_init(&layout->right, + middle, 0, hdisplay - middle, vdisplay); + break; + case DRM_MODE_FLAG_3D_FRAME_PACKING: + { + int vactive_space = mode->vtotal - vdisplay; + + layout->fb_width = hdisplay; + layout->fb_height = 2 * vdisplay + vactive_space; + + box_init(&layout->left, + 0, 0, hdisplay, vdisplay); + box_init(&layout->right, + 0, vdisplay + vactive_space, hdisplay, vdisplay); + break; + } + default: + igt_assert(0); } +} - if(test_all_modes){ - drmModeRmFB(drm_fd,fb_id); - drmModeSetCrtc(drm_fd, c->crtc, fb_id, 0, 0, &c->id, 1, 0); +static const char *stereo_mode_str(drmModeModeInfo *mode) +{ + unsigned int layout = mode->flags & DRM_MODE_FLAG_3D_MASK; + + switch (layout) { + case DRM_MODE_FLAG_3D_TOP_AND_BOTTOM: + return "TB"; + case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF: + return "SbSH"; + case DRM_MODE_FLAG_3D_FRAME_PACKING: + return "FP"; + default: + igt_assert(0); + } +} + +static uint32_t create_stereo_fb(drmModeModeInfo *mode, struct igt_fb *fb) +{ + struct stereo_fb_layout layout; + cairo_t *cr; + uint32_t fb_id; + + stereo_fb_layout_from_mode(&layout, mode); + fb_id = igt_create_fb(drm_fd, layout.fb_width, layout.fb_height, + igt_bpp_depth_to_drm_format(bpp, depth), + enable_tiling, fb); + cr = igt_get_cairo_ctx(drm_fd, fb); + + igt_paint_image(cr, IGT_DATADIR"/1080p-left.png", + layout.left.x, layout.left.y, + layout.left.width, layout.left.height); + igt_paint_image(cr, IGT_DATADIR"/1080p-right.png", + layout.right.x, layout.right.y, + layout.right.width, layout.right.height); + + cairo_destroy(cr); + + { + char buffer[64]; + + snprintf(buffer, sizeof(buffer), "%dx%d@%dHz-%s.png", + mode->hdisplay, + mode->vdisplay, + mode->vrefresh, + stereo_mode_str(mode)); + + igt_write_fb_to_png(drm_fd, fb, buffer); + } + + return fb_id; +} + +static void do_set_stereo_mode(struct connector *c) +{ + uint32_t fb_id; + struct igt_fb fb_info; + + fb_id = create_stereo_fb(&c->mode, &fb_info); + + if (drmModeSetCrtc(drm_fd, c->crtc, fb_id, 0, 0, + &c->id, 1, &c->mode)) { + fprintf(stderr, "failed to set mode (%dx%d@%dHz): %s\n", + width, height, c->mode.vrefresh, + strerror(errno)); + } +} + +static void +set_stereo_mode(struct connector *c) +{ + int i, n; + + + if (specified_mode_num != -1) + n = 1; + else + n = c->connector->count_modes; + + for (i = 0; i < n; i++) { + if (specified_mode_num == -1) + c->mode = c->connector->modes[i]; + + if (!c->mode_valid) + continue; + + if (!(c->mode.flags & DRM_MODE_FLAG_3D_MASK)) + continue; + + fprintf(stdout, "CRTC(%u): [%d]", c->crtc, i); + kmstest_dump_mode(&c->mode); + do_set_stereo_mode(c); + + if (qr_code) { + set_single(); + pause(); + } else if (sleep_between_modes) + sleep(sleep_between_modes); + + if (do_dpms) { + kmstest_set_connector_dpms(drm_fd, c->connector, DRM_MODE_DPMS_OFF); + sleep(sleep_between_modes); + kmstest_set_connector_dpms(drm_fd, c->connector, DRM_MODE_DPMS_ON); + } } drmModeFreeEncoder(c->encoder); @@ -580,25 +617,63 @@ int update_display(void) if (!connectors) return 0; - if (dump_info) { - dump_connectors_fd(drm_fd); - dump_crtcs_fd(drm_fd); - } + if (test_preferred_mode || test_all_modes || + force_mode || specified_disp_id != -1) { + unsigned long crtc_idx_mask = -1UL; - if (test_preferred_mode || test_all_modes || force_mode) { /* Find any connected displays */ for (c = 0; c < resources->count_connectors; c++) { - connectors[c].id = resources->connectors[c]; - set_mode(&connectors[c]); + struct connector *connector = &connectors[c]; + + connector->id = resources->connectors[c]; + if (specified_disp_id != -1 && + connector->id != specified_disp_id) + continue; + + connector_find_preferred_mode(connector->id, + crtc_idx_mask, + specified_mode_num, + connector); + if (!connector->mode_valid) + continue; + + set_mode(connector); + + if (test_preferred_mode || force_mode || + specified_mode_num != -1) + crtc_idx_mask &= ~(1 << connector->crtc_idx); + + } + } + + if (test_stereo_modes) { + for (c = 0; c < resources->count_connectors; c++) { + struct connector *connector = &connectors[c]; + + connector->id = resources->connectors[c]; + if (specified_disp_id != -1 && + connector->id != specified_disp_id) + continue; + + connector_find_preferred_mode(connector->id, + -1UL, + specified_mode_num, + connector); + if (!connector->mode_valid) + continue; + + set_stereo_mode(connector); } } + + free(connectors); drmModeFreeResources(resources); return 1; } -static char optstr[] = "hiaf:s:d:p:mrt"; +static char optstr[] = "3hiaf:s:d:p:mrto:j:"; -static void usage(char *name) +static void __attribute__((noreturn)) usage(char *name) { fprintf(stderr, "usage: %s [-hiasdpmtf]\n", name); fprintf(stderr, "\t-i\tdump info\n"); @@ -607,8 +682,11 @@ static void usage(char *name) fprintf(stderr, "\t-d\t<depth>\tbit depth of scanout buffer\n"); fprintf(stderr, "\t-p\t<planew,h>,<crtcx,y>,<crtcw,h> test overlay plane\n"); fprintf(stderr, "\t-m\ttest the preferred mode\n"); + fprintf(stderr, "\t-3\ttest all 3D modes\n"); fprintf(stderr, "\t-t\tuse a tiled framebuffer\n"); + fprintf(stderr, "\t-j\tdo dpms off, optional arg to select dpms leve (1-3)\n"); fprintf(stderr, "\t-r\tprint a QR code on the screen whose content is \"pass\" for the automatic test\n"); + fprintf(stderr, "\t-o\t<id of the display>,<number of the mode>\tonly test specified mode on the specified display\n"); fprintf(stderr, "\t-f\t<clock MHz>,<hdisp>,<hsync-start>,<hsync-end>,<htotal>,\n"); fprintf(stderr, "\t\t<vdisp>,<vsync-start>,<vsync-end>,<vtotal>\n"); fprintf(stderr, "\t\ttest force mode\n"); @@ -618,6 +696,12 @@ static void usage(char *name) #define dump_resource(res) if (res) dump_##res() +static void cleanup_and_exit(int ret) +{ + close(drm_fd); + exit(ret); +} + static gboolean input_event(GIOChannel *source, GIOCondition condition, gpointer data) { @@ -626,7 +710,7 @@ static gboolean input_event(GIOChannel *source, GIOCondition condition, count = read(g_io_channel_unix_get_fd(source), buf, sizeof(buf)); if (buf[0] == 'q' && (count == 1 || buf[1] == '\n')) { - exit(0); + cleanup_and_exit(0); } return TRUE; @@ -637,6 +721,7 @@ static void enter_exec_path( char **argv ) char *exec_path = NULL; char *pos = NULL; short len_path = 0; + int ret; len_path = strlen( argv[0] ); exec_path = (char*) malloc(len_path); @@ -646,10 +731,29 @@ static void enter_exec_path( char **argv ) if (pos != NULL) *(pos+1) = '\0'; - chdir(exec_path); + ret = chdir(exec_path); + igt_assert(ret == 0); free(exec_path); } +static void restore_termio_mode(int sig) +{ + tcsetattr(tio_fd, TCSANOW, &saved_tio); + close(tio_fd); +} + +static void set_termio_mode(void) +{ + struct termios tio; + + tio_fd = dup(STDIN_FILENO); + tcgetattr(tio_fd, &saved_tio); + igt_install_exit_handler(restore_termio_mode); + tio = saved_tio; + tio.c_lflag &= ~(ICANON | ECHO); + tcsetattr(tio_fd, TCSANOW, &tio); +} + int main(int argc, char **argv) { int c; @@ -657,14 +761,19 @@ int main(int argc, char **argv) GIOChannel *stdinchannel; GMainLoop *mainloop; float force_clock; + bool opt_dump_info = false; + + igt_skip_on_simulation(); enter_exec_path( argv ); - opterr = 0; while ((c = getopt(argc, argv, optstr)) != -1) { switch (c) { + case '3': + test_stereo_modes = 1; + break; case 'i': - dump_info = 1; + opt_dump_info = true; break; case 'a': test_all_modes = 1; @@ -681,6 +790,11 @@ int main(int argc, char **argv) case 's': sleep_between_modes = atoi(optarg); break; + case 'j': + do_dpms = atoi(optarg); + if (do_dpms == 0) + do_dpms = DRM_MODE_DPMS_OFF; + break; case 'd': depth = atoi(optarg); fprintf(stderr, "using depth %d\n", depth); @@ -701,20 +815,45 @@ int main(int argc, char **argv) case 'r': qr_code = 1; break; + case 'o': + sscanf(optarg, "%d,%d", &specified_disp_id, &specified_mode_num); + break; default: - fprintf(stderr, "unknown option %c\n", c); /* fall through */ case 'h': usage(argv[0]); break; } } - if (!test_all_modes && !force_mode && !dump_info && - !test_preferred_mode) + + set_termio_mode(); + + if (depth <= 8) + bpp = 8; + else if (depth <= 16) + bpp = 16; + else if (depth <= 32) + bpp = 32; + + if (!test_all_modes && !force_mode && !test_preferred_mode && + specified_mode_num == -1 && !test_stereo_modes) test_all_modes = 1; drm_fd = drm_open_any(); + if (test_stereo_modes && + drmSetClientCap(drm_fd, DRM_CLIENT_CAP_STEREO_3D, 1) < 0) { + fprintf(stderr, "DRM_CLIENT_CAP_STEREO_3D failed\n"); + goto out_close; + } + + if (opt_dump_info) { + dump_info(); + goto out_close; + } + + igt_set_vt_graphics_mode(); + mainloop = g_main_loop_new(NULL, FALSE); if (!mainloop) { fprintf(stderr, "failed to create glib mainloop\n"); @@ -747,7 +886,7 @@ int main(int argc, char **argv) goto out_stdio; } - if (dump_info || test_all_modes) + if (test_all_modes) goto out_stdio; g_main_loop_run(mainloop); diff --git a/tests/tools_test b/tests/tools_test new file mode 100755 index 00000000..4c5577a7 --- /dev/null +++ b/tests/tools_test @@ -0,0 +1,18 @@ +#!/bin/bash +# Test some of the most critical tools we have accidentally broken before. +# TODO: Possibly make tests parse output + +whoami | grep -q root || ( echo ERROR: not running as root; exit 1 ) + +SOURCE_DIR="$( dirname "${BASH_SOURCE[0]}" )" +. $SOURCE_DIR/drm_lib.sh + +# ARB_MODE has existed for many gens +do_or_die "$SOURCE_DIR/../tools/intel_reg_read 0x4030" + +do_or_die "$SOURCE_DIR/../tools/intel_reg_dumper" + +# TODO: Add more tests + +exit 0 + |