igt/gem_userptr_blits: Fix forked access test
[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 "ioctl_wrappers.h"
39 #include "i915_pciids.h"
40 #include "drmtest.h"
41 #include "intel_io.h"
42 #include "intel_chipset.h"
43
44 #define FORCEWAKE_MT 0xa188
45
46 struct thread {
47         pthread_t thread;
48         void *mmio;
49         int fd;
50         int bit;
51 };
52
53 static const struct pci_id_match match[] = {
54         INTEL_IVB_D_IDS(NULL),
55         INTEL_IVB_M_IDS(NULL),
56
57         INTEL_HSW_D_IDS(NULL),
58         INTEL_HSW_M_IDS(NULL),
59
60         { 0, 0, 0 },
61 };
62
63 static struct pci_device *__igfx_get(void)
64 {
65         struct pci_device *dev;
66
67         if (pci_system_init())
68                 return 0;
69
70         dev = pci_device_find_by_slot(0, 0, 2, 0);
71         if (dev == NULL || dev->vendor_id != 0x8086) {
72                 struct pci_device_iterator *iter;
73
74                 iter = pci_id_match_iterator_create(match);
75                 if (!iter)
76                         return 0;
77
78                 dev = pci_device_next(iter);
79                 pci_iterator_destroy(iter);
80         }
81
82         return dev;
83 }
84
85 static void *igfx_get_mmio(void)
86 {
87         struct pci_device *pci = __igfx_get();
88         int error;
89
90         igt_skip_on(pci == NULL);
91         igt_skip_on(intel_gen(pci->device_id) != 7);
92
93         error = pci_device_probe(pci);
94         igt_assert(error == 0);
95
96         error = pci_device_map_range(pci,
97                                      pci->regions[0].base_addr,
98                                      2*1024*1024,
99                                      PCI_DEV_MAP_FLAG_WRITABLE,
100                                      &mmio);
101         igt_assert(error == 0);
102         igt_assert(mmio != NULL);
103
104         return mmio;
105 }
106
107 static void *thread(void *arg)
108 {
109         struct thread *t = arg;
110         uint32_t *forcewake_mt = (uint32_t *)((char *)t->mmio + FORCEWAKE_MT);
111         uint32_t bit = 1 << t->bit;
112
113         while (1) {
114                 *forcewake_mt = bit << 16 | bit;
115                 igt_assert(*forcewake_mt & bit);
116                 *forcewake_mt = bit << 16;
117                 igt_assert((*forcewake_mt & bit) == 0);
118         }
119
120         return NULL;
121 }
122
123 #define MI_LOAD_REGISTER_IMM                    (0x22<<23)
124 #define MI_STORE_REGISTER_MEM                   (0x24<<23)
125
126 igt_simple_main
127 {
128         struct thread t[16];
129         int i;
130
131         t[0].fd = drm_open_any();
132         t[0].mmio = igfx_get_mmio();
133
134         for (i = 2; i < 16; i++) {
135                 t[i] = t[0];
136                 t[i].bit = i;
137                 pthread_create(&t[i].thread, NULL, thread, &t[i]);
138         }
139
140         sleep(2);
141
142         for (i = 0; i < 1000; i++) {
143                 uint32_t *p;
144                 struct drm_i915_gem_execbuffer2 execbuf;
145                 struct drm_i915_gem_exec_object2 exec[2];
146                 struct drm_i915_gem_relocation_entry reloc[2];
147                 uint32_t b[] = {
148                         MI_LOAD_REGISTER_IMM | 1,
149                         FORCEWAKE_MT,
150                         2 << 16 | 2,
151                         MI_STORE_REGISTER_MEM | 1,
152                         FORCEWAKE_MT,
153                         0, // to be patched
154                         MI_LOAD_REGISTER_IMM | 1,
155                         FORCEWAKE_MT,
156                         2 << 16,
157                         MI_STORE_REGISTER_MEM | 1,
158                         FORCEWAKE_MT,
159                         1 * sizeof(uint32_t), // to be patched
160                         MI_BATCH_BUFFER_END,
161                         0
162                 };
163
164                 memset(exec, 0, sizeof(exec));
165                 exec[1].handle = gem_create(t[0].fd, 4096);
166                 exec[1].relocation_count = 2;
167                 exec[1].relocs_ptr = (uintptr_t)reloc;
168                 gem_write(t[0].fd, exec[1].handle, 0, b, sizeof(b));
169                 exec[0].handle = gem_create(t[0].fd, 4096);
170
171                 reloc[0].offset = 5 * sizeof(uint32_t);
172                 reloc[0].delta = 0;
173                 reloc[0].target_handle = exec[0].handle;
174                 reloc[0].read_domains = I915_GEM_DOMAIN_RENDER;
175                 reloc[0].write_domain = I915_GEM_DOMAIN_RENDER;
176                 reloc[0].presumed_offset = 0;
177
178                 reloc[1].offset = 11 * sizeof(uint32_t);
179                 reloc[1].delta = 1 * sizeof(uint32_t);
180                 reloc[1].target_handle = exec[0].handle;
181                 reloc[1].read_domains = I915_GEM_DOMAIN_RENDER;
182                 reloc[1].write_domain = I915_GEM_DOMAIN_RENDER;
183                 reloc[1].presumed_offset = 0;
184
185                 memset(&execbuf, 0, sizeof(execbuf));
186                 execbuf.buffers_ptr = (uintptr_t)&exec;
187                 execbuf.buffer_count = 2;
188                 execbuf.batch_len = sizeof(b);
189                 execbuf.flags = I915_EXEC_SECURE;
190
191                 gem_execbuf(t[0].fd, &execbuf);
192                 gem_sync(t[0].fd, exec[1].handle);
193
194                 p = gem_mmap(t[0].fd, exec[0].handle, 4096, PROT_READ);
195
196                 igt_info("[%d]={ %08x %08x }\n", i, p[0], p[1]);
197                 igt_assert(p[0] & 2);
198                 igt_assert((p[1] & 2) == 0);
199
200                 munmap(p, 4096);
201                 gem_close(t[0].fd, exec[0].handle);
202                 gem_close(t[0].fd, exec[1].handle);
203
204                 usleep(1000);
205         }
206 }