blob: 0158199fd57287754cbabd279e0fbcec075fc953 [file] [log] [blame]
Chia-I Wu00a23b22014-08-20 15:28:08 +08001/*
2 * XGL
3 *
4 * Copyright (C) 2014 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#ifndef CMD_PRIV_H
26#define CMD_PRIV_H
27
Chia-I Wue24c3292014-08-21 14:05:23 +080028#include "genhw/genhw.h"
Chia-I Wu32710d72014-08-20 16:05:22 +080029#include "dev.h"
30#include "gpu.h"
Chia-I Wu00a23b22014-08-20 15:28:08 +080031#include "cmd.h"
32
Chia-I Wu32710d72014-08-20 16:05:22 +080033#define CMD_ASSERT(cmd, min_gen, max_gen) \
34 INTEL_GPU_ASSERT((cmd)->dev->gpu, (min_gen), (max_gen))
35
Chia-I Wu958d1b72014-08-21 11:28:11 +080036struct intel_cmd_reloc {
Chia-I Wue24c3292014-08-21 14:05:23 +080037 struct intel_cmd_writer *writer;
Chia-I Wu958d1b72014-08-21 11:28:11 +080038 XGL_UINT pos;
39
40 uint32_t val;
Chia-I Wu9ee38722014-08-25 12:11:36 +080041 struct intel_bo *bo;
Chia-I Wu958d1b72014-08-21 11:28:11 +080042
Chia-I Wu32a22462014-08-26 14:13:46 +080043 uint32_t flags;
Chia-I Wu958d1b72014-08-21 11:28:11 +080044};
45
Chia-I Wu9f039862014-08-20 15:39:56 +080046static inline int cmd_gen(const struct intel_cmd *cmd)
47{
48 return intel_gpu_gen(cmd->dev->gpu);
49}
50
Chia-I Wucdff0592014-08-22 09:27:36 +080051static inline void cmd_reserve_reloc(struct intel_cmd *cmd,
52 XGL_UINT reloc_len)
53{
54 /* fail silently */
55 if (cmd->reloc_used + reloc_len > cmd->reloc_count) {
56 cmd->reloc_used = 0;
57 cmd->result = XGL_ERROR_TOO_MANY_MEMORY_REFERENCES;
58 }
59 assert(cmd->reloc_used + reloc_len <= cmd->reloc_count);
60}
61
Chia-I Wue24c3292014-08-21 14:05:23 +080062void cmd_writer_grow(struct intel_cmd *cmd,
63 struct intel_cmd_writer *writer);
Chia-I Wu00a23b22014-08-20 15:28:08 +080064
Chia-I Wu32710d72014-08-20 16:05:22 +080065/**
Chia-I Wubda55fd2014-08-25 12:46:10 +080066 * Add a reloc at \p pos. No error checking.
Chia-I Wucdff0592014-08-22 09:27:36 +080067 */
68static inline void cmd_writer_add_reloc(struct intel_cmd *cmd,
69 struct intel_cmd_writer *writer,
Chia-I Wubda55fd2014-08-25 12:46:10 +080070 XGL_UINT pos, uint32_t val,
Chia-I Wu9ee38722014-08-25 12:11:36 +080071 struct intel_bo *bo,
Chia-I Wu32a22462014-08-26 14:13:46 +080072 uint32_t flags)
Chia-I Wucdff0592014-08-22 09:27:36 +080073{
74 struct intel_cmd_reloc *reloc = &cmd->relocs[cmd->reloc_used];
75
76 assert(cmd->reloc_used < cmd->reloc_count);
77
78 reloc->writer = writer;
Chia-I Wubda55fd2014-08-25 12:46:10 +080079 reloc->pos = pos;
Chia-I Wucdff0592014-08-22 09:27:36 +080080 reloc->val = val;
Chia-I Wu9ee38722014-08-25 12:11:36 +080081 reloc->bo = bo;
Chia-I Wu32a22462014-08-26 14:13:46 +080082 reloc->flags = flags;
Chia-I Wucdff0592014-08-22 09:27:36 +080083
84 cmd->reloc_used++;
85}
86
87/**
88 * Reserve \p len DWords in the batch buffer for building a hardware command.
Chia-I Wue24c3292014-08-21 14:05:23 +080089 */
90static inline void cmd_batch_reserve(struct intel_cmd *cmd, XGL_UINT len)
91{
92 struct intel_cmd_writer *writer = &cmd->batch;
93
94 if (writer->used + len > writer->size)
95 cmd_writer_grow(cmd, writer);
96 assert(writer->used + len <= writer->size);
97}
98
99/**
Chia-I Wucdff0592014-08-22 09:27:36 +0800100 * Reserve \p len DWords in the batch buffer and \p reloc_len relocs for
101 * building a hardware command.
102 */
103static inline void cmd_batch_reserve_reloc(struct intel_cmd *cmd,
104 XGL_UINT len, XGL_UINT reloc_len)
105{
106 cmd_reserve_reloc(cmd, reloc_len);
107 cmd_batch_reserve(cmd, len);
108}
109
110/**
111 * Add a DWord to the hardware command being built. No error checking.
Chia-I Wue24c3292014-08-21 14:05:23 +0800112 */
113static inline void cmd_batch_write(struct intel_cmd *cmd, uint32_t val)
114{
115 struct intel_cmd_writer *writer = &cmd->batch;
116
117 assert(writer->used < writer->size);
118 ((uint32_t *) writer->ptr_opaque)[writer->used++] = val;
119}
120
121/**
Chia-I Wucdff0592014-08-22 09:27:36 +0800122 * Add \p len DWords to the hardware command being built. No error checking.
123 */
124static inline void cmd_batch_write_n(struct intel_cmd *cmd,
125 const uint32_t *vals, XGL_UINT len)
126{
127 struct intel_cmd_writer *writer = &cmd->batch;
128
129 assert(writer->used + len <= writer->size);
130
131 memcpy((uint32_t *) writer->ptr_opaque + writer->used,
132 vals, sizeof(uint32_t) * len);
133 writer->used += len;
134}
135
136/**
137 * Add a reloc to the hardware command being built. No error checking.
Chia-I Wue24c3292014-08-21 14:05:23 +0800138 */
139static inline void cmd_batch_reloc(struct intel_cmd *cmd,
Chia-I Wu9ee38722014-08-25 12:11:36 +0800140 uint32_t val, struct intel_bo *bo,
Chia-I Wu32a22462014-08-26 14:13:46 +0800141 uint32_t flags)
Chia-I Wue24c3292014-08-21 14:05:23 +0800142{
143 struct intel_cmd_writer *writer = &cmd->batch;
144
Chia-I Wu32a22462014-08-26 14:13:46 +0800145 cmd_writer_add_reloc(cmd, writer, writer->used, val, bo, flags);
Chia-I Wu5e25c272014-08-21 20:19:12 +0800146
Chia-I Wue24c3292014-08-21 14:05:23 +0800147 writer->used++;
148}
149
150/**
Chia-I Wu48c283d2014-08-25 23:13:46 +0800151 * Begin the batch buffer.
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800152 */
153static inline void cmd_batch_begin(struct intel_cmd *cmd)
154{
Chia-I Wu48c283d2014-08-25 23:13:46 +0800155 /* STATE_BASE_ADDRESS */
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800156 const uint8_t cmd_len = 10;
157 const uint32_t dw0 = GEN_RENDER_CMD(COMMON, GEN6, STATE_BASE_ADDRESS) |
158 (cmd_len - 2);
159
Chia-I Wu48c283d2014-08-25 23:13:46 +0800160 /*
161 * assume all workarounds have been emitted for we do not need them for a
162 * fresh batch buffer
163 */
164 cmd->bind.wa_flags = 0xffffffff;
165
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800166 CMD_ASSERT(cmd, 6, 7.5);
167
168 cmd_batch_reserve(cmd, cmd_len);
169
170 /* relocs are not added until cmd_batch_end() */
171 assert(cmd->batch.used == 0);
172
173 cmd_batch_write(cmd, dw0);
174
175 /* start offsets */
176 cmd_batch_write(cmd, 1);
177 cmd_batch_write(cmd, 1);
178 cmd_batch_write(cmd, 1);
179 cmd_batch_write(cmd, 1);
180 cmd_batch_write(cmd, 1);
181 /* end offsets */
182 cmd_batch_write(cmd, 1);
183 cmd_batch_write(cmd, 1 + 0xfffff000);
184 cmd_batch_write(cmd, 1 + 0xfffff000);
185 cmd_batch_write(cmd, 1);
186}
187
188/**
Chia-I Wue24c3292014-08-21 14:05:23 +0800189 * End the batch buffer.
190 */
191static inline void cmd_batch_end(struct intel_cmd *cmd)
192{
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800193 struct intel_cmd_writer *writer = &cmd->batch;
194 const struct intel_cmd_writer *state = &cmd->state;
195 const struct intel_cmd_writer *kernel = &cmd->kernel;
196
197 cmd_reserve_reloc(cmd, 5);
Chia-I Wu32a22462014-08-26 14:13:46 +0800198 cmd_writer_add_reloc(cmd, writer, 2, 1, state->bo, 0);
199 cmd_writer_add_reloc(cmd, writer, 3, 1, state->bo, 0);
200 cmd_writer_add_reloc(cmd, writer, 5, 1, kernel->bo, 0);
201 cmd_writer_add_reloc(cmd, writer, 7, 1 +
202 (state->size << 2), state->bo, 0);
203 cmd_writer_add_reloc(cmd, writer, 9, 1 +
204 (kernel->size << 2), kernel->bo, 0);
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800205
Chia-I Wue24c3292014-08-21 14:05:23 +0800206 if (cmd->batch.used & 1) {
207 cmd_batch_reserve(cmd, 1);
208 cmd_batch_write(cmd, GEN_MI_CMD(MI_BATCH_BUFFER_END));
209 } else {
210 cmd_batch_reserve(cmd, 2);
211 cmd_batch_write(cmd, GEN_MI_CMD(MI_BATCH_BUFFER_END));
212 cmd_batch_write(cmd, GEN_MI_CMD(MI_NOOP));
213 }
Chia-I Wu343b1372014-08-20 16:39:20 +0800214}
215
Chia-I Wu24565ee2014-08-21 20:24:31 +0800216/**
Chia-I Wucdff0592014-08-22 09:27:36 +0800217 * Reserve \p len DWords in the state buffer for building a hardware state.
218 * The current writer position is aligned to \p alignment first. Both the
219 * pointer to the reserved region and the aligned position are returned.
220 *
221 * Note that the returned pointer is only valid until the next reserve call.
Chia-I Wu24565ee2014-08-21 20:24:31 +0800222 */
223static inline uint32_t *cmd_state_reserve(struct intel_cmd *cmd, XGL_UINT len,
224 XGL_UINT alignment, XGL_UINT *pos)
225{
226 struct intel_cmd_writer *writer = &cmd->state;
227 XGL_UINT aligned;
228
229 assert(alignment && u_is_pow2(alignment));
230 aligned = u_align(writer->used, alignment);
231
232 if (aligned + len > writer->size)
233 cmd_writer_grow(cmd, writer);
234 assert(aligned + len <= writer->size);
235
236 writer->used = aligned;
237 *pos = aligned;
238
239 return &((uint32_t *) writer->ptr_opaque)[writer->used];
240}
241
242/**
Chia-I Wucdff0592014-08-22 09:27:36 +0800243 * Similar to \p cmd_state_reserve, except that \p reloc_len relocs are also
244 * reserved.
Chia-I Wu24565ee2014-08-21 20:24:31 +0800245 */
Chia-I Wucdff0592014-08-22 09:27:36 +0800246static inline uint32_t *cmd_state_reserve_reloc(struct intel_cmd *cmd,
247 XGL_UINT len,
248 XGL_UINT reloc_len,
249 XGL_UINT alignment,
250 XGL_UINT *pos)
Chia-I Wu24565ee2014-08-21 20:24:31 +0800251{
Chia-I Wucdff0592014-08-22 09:27:36 +0800252 cmd_reserve_reloc(cmd, reloc_len);
253 return cmd_state_reserve(cmd, len, alignment, pos);
Chia-I Wu24565ee2014-08-21 20:24:31 +0800254}
255
256/**
Chia-I Wubda55fd2014-08-25 12:46:10 +0800257 * Add a reloc at \p offset, relative to the current writer position. No
258 * error checking.
259 */
260static inline void cmd_state_reloc(struct intel_cmd *cmd,
261 XGL_INT offset, uint32_t val,
262 struct intel_bo *bo,
Chia-I Wu32a22462014-08-26 14:13:46 +0800263 uint32_t flags)
Chia-I Wubda55fd2014-08-25 12:46:10 +0800264{
265 struct intel_cmd_writer *writer = &cmd->state;
266
Chia-I Wu32a22462014-08-26 14:13:46 +0800267 cmd_writer_add_reloc(cmd, writer, writer->used + offset, val, bo, flags);
Chia-I Wubda55fd2014-08-25 12:46:10 +0800268}
269
270/**
Chia-I Wucdff0592014-08-22 09:27:36 +0800271 * Advance the writer position of the state buffer. No error checking.
Chia-I Wu24565ee2014-08-21 20:24:31 +0800272 */
273static inline void cmd_state_advance(struct intel_cmd *cmd, XGL_UINT len)
274{
275 struct intel_cmd_writer *writer = &cmd->state;
276
277 assert(writer->used + len <= writer->size);
278 writer->used += len;
279}
280
281/**
Chia-I Wucdff0592014-08-22 09:27:36 +0800282 * A convenient function to copy a hardware state of \p len DWords into the
283 * state buffer. The position of the state is returned.
Chia-I Wu24565ee2014-08-21 20:24:31 +0800284 */
285static inline XGL_UINT cmd_state_copy(struct intel_cmd *cmd,
286 const uint32_t *vals, XGL_UINT len,
287 XGL_UINT alignment)
288{
289 uint32_t *dst;
290 XGL_UINT pos;
291
292 dst = cmd_state_reserve(cmd, len, alignment, &pos);
293 memcpy(dst, vals, sizeof(uint32_t) * len);
294 cmd_state_advance(cmd, len);
295
296 return pos;
297}
298
Chia-I Wu1cbc0052014-08-25 09:50:12 +0800299static inline XGL_UINT cmd_kernel_copy(struct intel_cmd *cmd,
300 const void *kernel, XGL_SIZE size)
301{
302 /*
303 * From the Sandy Bridge PRM, volume 4 part 2, page 112:
304 *
305 * "Due to prefetch of the instruction stream, the EUs may attempt to
306 * access up to 8 instructions (128 bytes) beyond the end of the
307 * kernel program - possibly into the next memory page. Although
308 * these instructions will not be executed, software must account for
309 * the prefetch in order to avoid invalid page access faults."
310 */
311 const XGL_UINT prefetch_len = 128 / sizeof(uint32_t);
312 /* kernels are aligned to 64-byte */
313 const XGL_UINT kernel_align = 64 / sizeof(uint32_t);
314 const XGL_UINT kernel_len = ((size + 3) & ~3) / sizeof(uint32_t);
315 struct intel_cmd_writer *writer = &cmd->kernel;
316 XGL_UINT kernel_pos;
317
318 kernel_pos = u_align(writer->used, kernel_align);
319 if (kernel_pos + kernel_len + prefetch_len > writer->size)
320 cmd_writer_grow(cmd, writer);
321 assert(kernel_pos + kernel_len + prefetch_len <= writer->size);
322
323 memcpy(&((uint32_t *) writer->ptr_opaque)[kernel_pos], kernel, size);
324 writer->used = kernel_pos + kernel_len;
325
326 return kernel_pos;
327}
328
Chia-I Wu00a23b22014-08-20 15:28:08 +0800329#endif /* CMD_PRIV_H */