tests: Add gen7_forcewake_mt
[platform/upstream/intel-gpu-tools.git] / tests / gen7_forcewake_mt.c
1 /*
2  * Copyright © 2014 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  * Authors:
24  *    Chris Wilson <chris@chris-wilson.co.uk>
25  *
26  */
27
28 /*
29  * Testcase: Exercise a suspect workaround required for FORCEWAKE_MT
30  *
31  */
32
33 #include <sys/types.h>
34 #include <pthread.h>
35 #include <string.h>
36
37 #include "drm.h"
38 #include "i915_drm.h"
39 #include "i915_pciids.h"
40 #include "drmtest.h"
41 #include "intel_gpu_tools.h"
42
43 #define FORCEWAKE_MT 0xa188
44
45 struct thread {
46         pthread_t thread;
47         void *mmio;
48         int fd;
49         int bit;
50 };
51
52 static const struct pci_id_match match[] = {
53         INTEL_IVB_D_IDS(NULL),
54         INTEL_IVB_M_IDS(NULL),
55
56         INTEL_HSW_D_IDS(NULL),
57         INTEL_HSW_M_IDS(NULL),
58
59         { 0, 0, 0 },
60 };
61
62 static struct pci_device *__igfx_get(void)
63 {
64         struct pci_device *dev;
65
66         if (pci_system_init())
67                 return 0;
68
69         dev = pci_device_find_by_slot(0, 0, 2, 0);
70         if (dev == NULL || dev->vendor_id != 0x8086) {
71                 struct pci_device_iterator *iter;
72
73                 iter = pci_id_match_iterator_create(match);
74                 if (!iter)
75                         return 0;
76
77                 dev = pci_device_next(iter);
78                 pci_iterator_destroy(iter);
79         }
80
81         return dev;
82 }
83
84 static void *igfx_get_mmio(void)
85 {
86         struct pci_device *pci = __igfx_get();
87         int error;
88
89         igt_skip_on(pci == NULL);
90         igt_skip_on(intel_gen(pci->device_id) != 7);
91
92         error = pci_device_probe(pci);
93         igt_assert(error == 0);
94
95         error = pci_device_map_range(pci,
96                                      pci->regions[0].base_addr,
97                                      2*1024*1024,
98                                      PCI_DEV_MAP_FLAG_WRITABLE,
99                                      &mmio);
100         igt_assert(error == 0);
101         igt_assert(mmio != NULL);
102
103         return mmio;
104 }
105
106 static void *thread(void *arg)
107 {
108         struct thread *t = arg;
109         uint32_t *forcewake_mt = (uint32_t *)((char *)t->mmio + FORCEWAKE_MT);
110         uint32_t bit = 1 << t->bit;
111
112         while (1) {
113                 *forcewake_mt = bit << 16 | bit;
114                 igt_assert(*forcewake_mt & bit);
115                 *forcewake_mt = bit << 16;
116                 igt_assert((*forcewake_mt & bit) == 0);
117         }
118
119         return NULL;
120 }
121
122 #define MI_LOAD_REGISTER_IMM                    (0x22<<23)
123 #define MI_STORE_REGISTER_MEM                   (0x24<<23| 1<<22)
124
125 igt_simple_main
126 {
127         struct thread t[16];
128         int i;
129
130         t[0].fd = drm_open_any();
131         t[0].mmio = igfx_get_mmio();
132
133         for (i = 2; i < 16; i++) {
134                 t[i] = t[0];
135                 t[i].bit = i;
136                 pthread_create(&t[i].thread, NULL, thread, &t[i]);
137         }
138
139         sleep(2);
140
141         for (i = 0; i < 1000; i++) {
142                 struct drm_i915_gem_execbuffer2 execbuf;
143                 struct drm_i915_gem_exec_object2 exec;
144                 struct drm_i915_gem_relocation_entry reloc[2];
145                 uint32_t b[] = {
146                         MI_LOAD_REGISTER_IMM | 1,
147                         FORCEWAKE_MT,
148                         2 << 16 | 2,
149                         MI_STORE_REGISTER_MEM | 1,
150                         FORCEWAKE_MT,
151                         5*sizeof(uint32_t),
152                         MI_LOAD_REGISTER_IMM | 1,
153                         FORCEWAKE_MT,
154                         2 << 16,
155                         MI_STORE_REGISTER_MEM | 1,
156                         FORCEWAKE_MT,
157                         11*sizeof(uint32_t),
158                         MI_BATCH_BUFFER_END,
159                         0
160                 };
161
162                 memset(&exec, 0, sizeof(exec));
163                 exec.handle = gem_create(t[0].fd, 4096);
164                 exec.relocation_count = 2;
165                 exec.relocs_ptr = (uintptr_t)reloc;
166                 //exec.flags = EXEC_OBJECT_NEEDS_GTT;
167                 gem_write(t[0].fd, exec.handle, 0, b, sizeof(b));
168
169                 reloc[0].offset = 5 * sizeof(uint32_t);
170                 reloc[0].delta = 5 * sizeof(uint32_t);
171                 reloc[0].target_handle = exec.handle;
172                 reloc[0].read_domains = I915_GEM_DOMAIN_INSTRUCTION;
173                 reloc[0].write_domain = 0;
174                 reloc[0].presumed_offset = 0;
175
176                 reloc[1].offset = 11 * sizeof(uint32_t);
177                 reloc[1].delta = 11 * sizeof(uint32_t);
178                 reloc[1].target_handle = exec.handle;
179                 reloc[1].read_domains = I915_GEM_DOMAIN_INSTRUCTION;
180                 reloc[1].write_domain = 0;
181                 reloc[1].presumed_offset = 0;
182
183                 memset(&execbuf, 0, sizeof(execbuf));
184                 execbuf.buffers_ptr = (uintptr_t)&exec;
185                 execbuf.buffer_count = 1;
186                 execbuf.batch_len = sizeof(b);
187                 execbuf.flags = I915_EXEC_SECURE;
188
189                 gem_execbuf(t[0].fd, &execbuf);
190                 gem_sync(t[0].fd, exec.handle);
191                 gem_read(t[0].fd, exec.handle, 0, b, sizeof(b));
192                 gem_close(t[0].fd, exec.handle);
193
194                 printf("[%d]={ %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x }\n",
195                        i, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12]);
196
197                 igt_assert(b[5] & 2);
198                 igt_assert((b[11] & 2) == 0);
199
200                 usleep(1000);
201         }
202 }