summaryrefslogtreecommitdiff
path: root/tests/intel/xe_huc_copy.c
blob: 6d8ca0776497a6a37ee3b5cd2f0f5d4f9ba8fc20 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
// SPDX-License-Identifier: MIT
/*
 * Copyright © 2022 Intel Corporation
 */

/**
 * TEST: Test HuC copy firmware.
 * Category: Core
 * Mega feature: General Core features
 * Sub-category: Firmware tests
 * Functionality: huc copy
 * Test category: functionality test
 * TODO: make the test more generic, getting rid of the PCI ID list
 * GPU requirements: This test currently requires TGL, and runs only if the
 *	PCI ID is 0x9A60, 0x9A68, 0x9A70, 0x9A40, 0x9A49, 0x9A59, 0x9A78,
 *	0x9AC0, 0x9AC9, 0x9AD9 or 0x9AF8
 */

#include <string.h>

#include "igt.h"
#include "lib/igt_syncobj.h"
#include "xe_drm.h"
#include "xe/xe_ioctl.h"
#include "xe/xe_query.h"

#define SIZE_DATA           0x1000
#define SIZE_BATCH          0x1000
#define SIZE_BUFFER_INPUT   SIZE_DATA
#define SIZE_BUFFER_OUTPUT  SIZE_DATA
#define ADDR_INPUT          0x200000
#define ADDR_OUTPUT         0x400000
#define ADDR_BATCH          0x600000

#define PARALLEL_VIDEO_PIPE     (0x3<<29)
#define HUC_MFX_WAIT            (PARALLEL_VIDEO_PIPE|(0x1<<27)|(0x1<<8))
#define HUC_IMEM_STATE          (PARALLEL_VIDEO_PIPE|(0x2<<27)|(0xb<<23)|(0x1<<16)|0x3)
#define HUC_PIPE_MODE_SELECT    (PARALLEL_VIDEO_PIPE|(0x2<<27)|(0xb<<23)|0x1)
#define HUC_START               (PARALLEL_VIDEO_PIPE|(0x2<<27)|(0xb<<23)|(0x21<<16))
#define HUC_VIRTUAL_ADDR_STATE  (PARALLEL_VIDEO_PIPE|(0x2<<27)|(0xb<<23)|(0x4<<16)|0x2f)
#define HUC_VIRTUAL_ADDR_REGION_NUM 16
#define HUC_VIRTUAL_ADDR_REGION_SRC 0
#define HUC_VIRTUAL_ADDR_REGION_DST 14

struct bo_dict_entry {
	uint64_t addr;
	uint32_t size;
	void *data;
};

static void
gen12_emit_huc_virtual_addr_state(uint64_t src_addr,
	uint64_t dst_addr,
	uint32_t *batch,
	int *i) {
	batch[(*i)++] = HUC_VIRTUAL_ADDR_STATE;

	for (int j = 0; j < HUC_VIRTUAL_ADDR_REGION_NUM; j++) {
		if (j == HUC_VIRTUAL_ADDR_REGION_SRC) {
			batch[(*i)++] = src_addr;
		} else if (j == HUC_VIRTUAL_ADDR_REGION_DST) {
			batch[(*i)++] = dst_addr;
		} else {
			batch[(*i)++] = 0;
		}
		batch[(*i)++] = 0;
		batch[(*i)++] = 0;
	}
}

static void
gen12_create_batch_huc_copy(uint32_t *batch,
	uint64_t src_addr,
	uint64_t dst_addr) {
	int i = 0;

	batch[i++] = HUC_IMEM_STATE;
	batch[i++] = 0;
	batch[i++] = 0;
	batch[i++] = 0;
	batch[i++] = 0x3;

	batch[i++] = HUC_MFX_WAIT;
	batch[i++] = HUC_MFX_WAIT;

	batch[i++] = HUC_PIPE_MODE_SELECT;
	batch[i++] = 0;
	batch[i++] = 0;

	batch[i++] = HUC_MFX_WAIT;

	gen12_emit_huc_virtual_addr_state(src_addr, dst_addr, batch, &i);

	batch[i++] = HUC_START;
	batch[i++] = 1;

	batch[i++] = MI_BATCH_BUFFER_END;
}

/**
 * SUBTEST: huc_copy
 * Description:
 *	Loads the HuC copy firmware to copy the content of
 *	the source buffer to the destination buffer. *
 */

static void
__test_huc_copy(int fd, uint32_t vm, struct drm_xe_engine_class_instance *hwe)
{
	uint32_t exec_queue;
	char *dinput;
	struct drm_xe_sync sync = { 0 };

#define BO_DICT_ENTRIES 3
	struct bo_dict_entry bo_dict[BO_DICT_ENTRIES] = {
		{ .addr = ADDR_INPUT, .size = SIZE_BUFFER_INPUT }, // input
		{ .addr = ADDR_OUTPUT, .size = SIZE_BUFFER_OUTPUT }, // output
		{ .addr = ADDR_BATCH, .size = SIZE_BATCH }, // batch
	};

	exec_queue = xe_exec_queue_create(fd, vm, hwe, 0);
	sync.type = DRM_XE_SYNC_TYPE_SYNCOBJ;
	sync.flags = DRM_XE_SYNC_FLAG_SIGNAL;
	sync.handle = syncobj_create(fd, 0);

	for(int i = 0; i < BO_DICT_ENTRIES; i++) {
		bo_dict[i].data = aligned_alloc(xe_get_default_alignment(fd), bo_dict[i].size);
		xe_vm_bind_userptr_async(fd, vm, 0, to_user_pointer(bo_dict[i].data), bo_dict[i].addr, bo_dict[i].size, &sync, 1);
		syncobj_wait(fd, &sync.handle, 1, INT64_MAX, 0, NULL);
		memset(bo_dict[i].data, 0, bo_dict[i].size);
	}
	dinput = (char *)bo_dict[0].data;
	srand(time(NULL));
	for(int i=0; i < SIZE_DATA; i++) {
		((char*) dinput)[i] = rand()/256;
	}
	gen12_create_batch_huc_copy(bo_dict[2].data, bo_dict[0].addr, bo_dict[1].addr);

	xe_exec_wait(fd, exec_queue, ADDR_BATCH);
	for(int i = 0; i < SIZE_DATA; i++) {
		igt_assert(((char*) bo_dict[1].data)[i] == ((char*) bo_dict[0].data)[i]);
	}

	for(int i = 0; i < BO_DICT_ENTRIES; i++) {
		xe_vm_unbind_async(fd, vm, 0, 0, bo_dict[i].addr, bo_dict[i].size, &sync, 1);
		syncobj_wait(fd, &sync.handle, 1, INT64_MAX, 0, NULL);
		free(bo_dict[i].data);
	}

	syncobj_destroy(fd, sync.handle);
	xe_exec_queue_destroy(fd, exec_queue);
}

static void
test_huc_copy(int fd)
{
	struct drm_xe_engine_class_instance *hwe;
	uint32_t vm;
	uint32_t tested_gts = 0;

	vm = xe_vm_create(fd, 0, 0);

	xe_for_each_engine(fd, hwe) {
		if (hwe->engine_class == DRM_XE_ENGINE_CLASS_VIDEO_DECODE &&
		    !(tested_gts & BIT(hwe->gt_id))) {
			tested_gts |= BIT(hwe->gt_id);
			__test_huc_copy(fd, vm, hwe);
		}
	}

	xe_vm_destroy(fd, vm);

	igt_require_f(tested_gts, "No video class engines found\n");
}

static bool
is_huc_running(int fd)
{
	char buf[4096];
	char *s;
	int gt;

	xe_for_each_gt(fd, gt) {
		char name[256];

		sprintf(name, "gt%d/uc/huc_info", gt);
		igt_debugfs_read(fd, name, buf);
		s = strstr(buf, "RUNNING");

		if (s)
			return true;
	}
	return false;
}

igt_main
{
	int xe;

	igt_fixture
		xe = drm_open_driver(DRIVER_XE);

	igt_subtest("huc_copy") {
		/*
		 * TODO: eventually need to differentiate huc failed to load vs
		 * platform doesnt have huc
		 */
		igt_skip_on(!is_huc_running(xe));
		test_huc_copy(xe);
	}

	igt_fixture
		drm_close_driver(xe);
}