summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/igt_gt.c54
-rw-r--r--lib/igt_gt.h3
2 files changed, 57 insertions, 0 deletions
diff --git a/lib/igt_gt.c b/lib/igt_gt.c
index 688ea5e6..f79728fd 100644
--- a/lib/igt_gt.c
+++ b/lib/igt_gt.c
@@ -343,3 +343,57 @@ void igt_set_stop_rings(enum stop_ring_flags flags)
"i915_ring_stop readback mismatch 0x%x vs 0x%x\n",
flags, current);
}
+
+static unsigned int clflush_size;
+
+int igt_setup_clflush(void)
+{
+ FILE *file;
+ char *line = NULL;
+ size_t size = 0;
+ int first_stanza = 1;
+ int has_clflush = 0;
+
+ if (clflush_size)
+ return 1;
+
+ file = fopen("/proc/cpuinfo", "r");
+ if (file == NULL)
+ return 0;
+
+ while (getline(&line, &size, file) != -1) {
+ if (strncmp(line, "processor", 9) == 0) {
+ if (!first_stanza)
+ break;
+ first_stanza = 0;
+ }
+
+ if (strncmp(line, "flags", 5) == 0) {
+ if (strstr(line, "clflush"))
+ has_clflush = 1;
+ }
+
+ if (strncmp(line, "clflush size", 12) == 0) {
+ char *colon = strchr(line, ':');
+ if (colon)
+ clflush_size = atoi(colon + 1);
+ }
+ }
+ free(line);
+ fclose(file);
+
+ return has_clflush && clflush_size;
+}
+
+void igt_clflush_range(void *addr, int size)
+{
+ char *p, *end;
+
+ end = (char *)addr + size;
+ p = (char *)((uintptr_t)addr & ~((uintptr_t)clflush_size - 1));
+
+ asm volatile("mfence" ::: "memory");
+ for (; p < end; p += clflush_size)
+ asm volatile("clflush %0" : "+m" (*(volatile char *)p));
+ asm volatile("mfence" ::: "memory");
+}
diff --git a/lib/igt_gt.h b/lib/igt_gt.h
index b70bbd15..4f8eff50 100644
--- a/lib/igt_gt.h
+++ b/lib/igt_gt.h
@@ -74,4 +74,7 @@ enum stop_ring_flags igt_to_stop_ring_flag(int ring);
void igt_set_stop_rings(enum stop_ring_flags flags);
enum stop_ring_flags igt_get_stop_rings(void);
+int igt_setup_clflush(void);
+void igt_clflush_range(void *addr, int size);
+
#endif /* IGT_GT_H */