vtest: move to multi-client support in vtest_renderer

This commit moves input/out_fd into vtest_context to allow multiple
clients, where each client is represented by a vtest_context and has
its own vtest_input.

Note that clients must know and trust each other, especially when it
comes to resources.  There is no conflict or ownership check in
vtest_create_resource or vtest_resource_unref respectively yet.
There is also no resource sharing support yet.

Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
Reviewed-By: Gert Wollny <gert.wollny@collabora.com>
Reviewed-By: Gurchetan Singh <gurchetansingh@chromium.org>
macos/master
Chia-I Wu 5 years ago
parent 1a01bdbefb
commit c6771ac666
  1. 6
      vtest/vtest.h
  2. 4
      vtest/vtest_fuzzer.c
  3. 105
      vtest/vtest_renderer.c
  4. 4
      vtest/vtest_server.c

@ -42,11 +42,11 @@ struct vtest_input {
int (*read)(struct vtest_input *input, void *buf, int size); int (*read)(struct vtest_input *input, void *buf, int size);
}; };
int vtest_init_renderer(struct vtest_input *input, int out_fd, int vtest_init_renderer(int ctx_flags, const char *render_device);
int ctx_flags, const char *render_device);
void vtest_cleanup_renderer(void); void vtest_cleanup_renderer(void);
int vtest_create_context(uint32_t length_dw, struct vtest_context **out_ctx); int vtest_create_context(struct vtest_input *input, int out_fd,
uint32_t length_dw, struct vtest_context **out_ctx);
void vtest_destroy_context(struct vtest_context *ctx); void vtest_destroy_context(struct vtest_context *ctx);
void vtest_set_current_context(struct vtest_context *ctx); void vtest_set_current_context(struct vtest_context *ctx);

@ -105,9 +105,9 @@ static void vtest_fuzzer_run_renderer(int out_fd, struct vtest_input *input,
break; break;
} }
ret = vtest_init_renderer(input, out_fd, ctx_flags, NULL); ret = vtest_init_renderer(ctx_flags, NULL);
if (ret >= 0) { if (ret >= 0) {
ret = vtest_create_context(header[0], &context); ret = vtest_create_context(input, out_fd, header[0], &context);
} }
if (ret < 0) { if (ret < 0) {
break; break;

@ -52,12 +52,13 @@ struct vtest_context {
int ctx_id; int ctx_id;
struct vtest_input *input;
int out_fd;
unsigned protocol_version; unsigned protocol_version;
}; };
struct vtest_renderer { struct vtest_renderer {
struct vtest_input *input;
int out_fd;
struct util_hash_table *iovec_hash; struct util_hash_table *iovec_hash;
const char *rendernode_name; const char *rendernode_name;
@ -236,14 +237,11 @@ int vtest_buf_read(struct vtest_input *input, void *buf, int size)
return size; return size;
} }
int vtest_init_renderer(struct vtest_input *input, int out_fd, int vtest_init_renderer(int ctx_flags, const char *render_device)
int ctx_flags, const char *render_device)
{ {
int ret; int ret;
renderer.iovec_hash = util_hash_table_create(hash_func, compare_iovecs, free_iovec); renderer.iovec_hash = util_hash_table_create(hash_func, compare_iovecs, free_iovec);
renderer.input = input;
renderer.out_fd = out_fd;
renderer.rendernode_name = render_device; renderer.rendernode_name = render_device;
list_inithead(&renderer.active_contexts); list_inithead(&renderer.active_contexts);
list_inithead(&renderer.free_contexts); list_inithead(&renderer.free_contexts);
@ -283,11 +281,10 @@ void vtest_cleanup_renderer(void)
util_hash_table_destroy(renderer.iovec_hash); util_hash_table_destroy(renderer.iovec_hash);
renderer.iovec_hash = NULL; renderer.iovec_hash = NULL;
renderer.input = NULL;
renderer.out_fd = -1;
} }
static struct vtest_context *vtest_new_context(void) static struct vtest_context *vtest_new_context(struct vtest_input *input,
int out_fd)
{ {
struct vtest_context *ctx; struct vtest_context *ctx;
@ -302,6 +299,9 @@ static struct vtest_context *vtest_new_context(void)
list_del(&ctx->head); list_del(&ctx->head);
} }
ctx->input = input;
ctx->out_fd = out_fd;
/* By default we support version 0 unless VCMD_PROTOCOL_VERSION is sent */ /* By default we support version 0 unless VCMD_PROTOCOL_VERSION is sent */
ctx->protocol_version = 0; ctx->protocol_version = 0;
@ -317,7 +317,8 @@ static void vtest_free_context(struct vtest_context *ctx, bool cleanup)
} }
} }
int vtest_create_context(uint32_t length, struct vtest_context **out_ctx) int vtest_create_context(struct vtest_input *input, int out_fd,
uint32_t length, struct vtest_context **out_ctx)
{ {
struct vtest_context *ctx; struct vtest_context *ctx;
char *vtestname; char *vtestname;
@ -327,7 +328,7 @@ int vtest_create_context(uint32_t length, struct vtest_context **out_ctx)
return -1; return -1;
} }
ctx = vtest_new_context(); ctx = vtest_new_context(input, out_fd);
if (!ctx) { if (!ctx) {
return -1; return -1;
} }
@ -338,7 +339,7 @@ int vtest_create_context(uint32_t length, struct vtest_context **out_ctx)
goto end; goto end;
} }
ret = renderer.input->read(renderer.input, vtestname, length); ret = ctx->input->read(ctx->input, vtestname, length);
if (ret != (int)length) { if (ret != (int)length) {
ret = -1; ret = -1;
goto end; goto end;
@ -382,12 +383,13 @@ static struct vtest_context *vtest_get_current_context(void)
int vtest_ping_protocol_version(UNUSED uint32_t length_dw) int vtest_ping_protocol_version(UNUSED uint32_t length_dw)
{ {
struct vtest_context *ctx = vtest_get_current_context();
uint32_t hdr_buf[VTEST_HDR_SIZE]; uint32_t hdr_buf[VTEST_HDR_SIZE];
int ret; int ret;
hdr_buf[VTEST_CMD_LEN] = VCMD_PING_PROTOCOL_VERSION_SIZE; hdr_buf[VTEST_CMD_LEN] = VCMD_PING_PROTOCOL_VERSION_SIZE;
hdr_buf[VTEST_CMD_ID] = VCMD_PING_PROTOCOL_VERSION; hdr_buf[VTEST_CMD_ID] = VCMD_PING_PROTOCOL_VERSION;
ret = vtest_block_write(renderer.out_fd, hdr_buf, sizeof(hdr_buf)); ret = vtest_block_write(ctx->out_fd, hdr_buf, sizeof(hdr_buf));
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -403,7 +405,7 @@ int vtest_protocol_version(UNUSED uint32_t length_dw)
unsigned version; unsigned version;
int ret; int ret;
ret = renderer.input->read(renderer.input, &version_buf, sizeof(version_buf)); ret = ctx->input->read(ctx->input, &version_buf, sizeof(version_buf));
if (ret != sizeof(version_buf)) if (ret != sizeof(version_buf))
return -1; return -1;
@ -433,12 +435,12 @@ int vtest_protocol_version(UNUSED uint32_t length_dw)
version_buf[VCMD_PROTOCOL_VERSION_VERSION] = ctx->protocol_version; version_buf[VCMD_PROTOCOL_VERSION_VERSION] = ctx->protocol_version;
ret = vtest_block_write(renderer.out_fd, hdr_buf, sizeof(hdr_buf)); ret = vtest_block_write(ctx->out_fd, hdr_buf, sizeof(hdr_buf));
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
ret = vtest_block_write(renderer.out_fd, version_buf, sizeof(version_buf)); ret = vtest_block_write(ctx->out_fd, version_buf, sizeof(version_buf));
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -448,6 +450,7 @@ int vtest_protocol_version(UNUSED uint32_t length_dw)
int vtest_send_caps2(UNUSED uint32_t length_dw) int vtest_send_caps2(UNUSED uint32_t length_dw)
{ {
struct vtest_context *ctx = vtest_get_current_context();
uint32_t hdr_buf[2]; uint32_t hdr_buf[2];
void *caps_buf; void *caps_buf;
int ret; int ret;
@ -468,12 +471,12 @@ int vtest_send_caps2(UNUSED uint32_t length_dw)
hdr_buf[0] = max_size + 1; hdr_buf[0] = max_size + 1;
hdr_buf[1] = 2; hdr_buf[1] = 2;
ret = vtest_block_write(renderer.out_fd, hdr_buf, 8); ret = vtest_block_write(ctx->out_fd, hdr_buf, 8);
if (ret < 0) { if (ret < 0) {
goto end; goto end;
} }
vtest_block_write(renderer.out_fd, caps_buf, max_size); vtest_block_write(ctx->out_fd, caps_buf, max_size);
if (ret < 0) { if (ret < 0) {
goto end; goto end;
} }
@ -485,6 +488,7 @@ end:
int vtest_send_caps(UNUSED uint32_t length_dw) int vtest_send_caps(UNUSED uint32_t length_dw)
{ {
struct vtest_context *ctx = vtest_get_current_context();
uint32_t max_ver, max_size; uint32_t max_ver, max_size;
void *caps_buf; void *caps_buf;
uint32_t hdr_buf[2]; uint32_t hdr_buf[2];
@ -501,12 +505,12 @@ int vtest_send_caps(UNUSED uint32_t length_dw)
hdr_buf[0] = max_size + 1; hdr_buf[0] = max_size + 1;
hdr_buf[1] = 1; hdr_buf[1] = 1;
ret = vtest_block_write(renderer.out_fd, hdr_buf, 8); ret = vtest_block_write(ctx->out_fd, hdr_buf, 8);
if (ret < 0) { if (ret < 0) {
goto end; goto end;
} }
vtest_block_write(renderer.out_fd, caps_buf, max_size); vtest_block_write(ctx->out_fd, caps_buf, max_size);
if (ret < 0) { if (ret < 0) {
goto end; goto end;
} }
@ -523,8 +527,8 @@ int vtest_create_resource(UNUSED uint32_t length_dw)
struct virgl_renderer_resource_create_args args; struct virgl_renderer_resource_create_args args;
int ret; int ret;
ret = renderer.input->read(renderer.input, &res_create_buf, ret = ctx->input->read(ctx->input, &res_create_buf,
sizeof(res_create_buf)); sizeof(res_create_buf));
if (ret != sizeof(res_create_buf)) { if (ret != sizeof(res_create_buf)) {
return -1; return -1;
} }
@ -542,6 +546,7 @@ int vtest_create_resource(UNUSED uint32_t length_dw)
args.nr_samples = res_create_buf[VCMD_RES_CREATE_NR_SAMPLES]; args.nr_samples = res_create_buf[VCMD_RES_CREATE_NR_SAMPLES];
args.flags = 0; args.flags = 0;
/* XXX check that args.handle does not already exist */
ret = virgl_renderer_resource_create(&args, NULL, 0); ret = virgl_renderer_resource_create(&args, NULL, 0);
virgl_renderer_ctx_attach_resource(ctx->ctx_id, args.handle); virgl_renderer_ctx_attach_resource(ctx->ctx_id, args.handle);
@ -556,8 +561,8 @@ int vtest_create_resource2(UNUSED uint32_t length_dw)
struct iovec *iovec; struct iovec *iovec;
int ret, fd; int ret, fd;
ret = renderer.input->read(renderer.input, &res_create_buf, ret = ctx->input->read(ctx->input, &res_create_buf,
sizeof(res_create_buf)); sizeof(res_create_buf));
if (ret != sizeof(res_create_buf)) { if (ret != sizeof(res_create_buf)) {
return -1; return -1;
} }
@ -614,7 +619,7 @@ int vtest_create_resource2(UNUSED uint32_t length_dw)
return -ENOMEM; return -ENOMEM;
} }
ret = vtest_send_fd(renderer.out_fd, fd); ret = vtest_send_fd(ctx->out_fd, fd);
if (ret < 0) { if (ret < 0) {
close(fd); close(fd);
munmap(iovec->iov_base, iovec->iov_len); munmap(iovec->iov_base, iovec->iov_len);
@ -637,13 +642,14 @@ int vtest_resource_unref(UNUSED uint32_t length_dw)
int ret; int ret;
uint32_t handle; uint32_t handle;
ret = renderer.input->read(renderer.input, &res_unref_buf, ret = ctx->input->read(ctx->input, &res_unref_buf,
sizeof(res_unref_buf)); sizeof(res_unref_buf));
if (ret != sizeof(res_unref_buf)) { if (ret != sizeof(res_unref_buf)) {
return -1; return -1;
} }
handle = res_unref_buf[VCMD_RES_UNREF_RES_HANDLE]; handle = res_unref_buf[VCMD_RES_UNREF_RES_HANDLE];
/* XXX check that handle is owned by ctx */
virgl_renderer_ctx_attach_resource(ctx->ctx_id, handle); virgl_renderer_ctx_attach_resource(ctx->ctx_id, handle);
virgl_renderer_resource_detach_iov(handle, NULL, NULL); virgl_renderer_resource_detach_iov(handle, NULL, NULL);
@ -668,7 +674,7 @@ int vtest_submit_cmd(uint32_t length_dw)
return -1; return -1;
} }
ret = renderer.input->read(renderer.input, cbuf, length_dw * 4); ret = ctx->input->read(ctx->input, cbuf, length_dw * 4);
if (ret != (int)length_dw * 4) { if (ret != (int)length_dw * 4) {
free(cbuf); free(cbuf);
return -1; return -1;
@ -708,8 +714,8 @@ int vtest_transfer_get(UNUSED uint32_t length_dw)
void *ptr; void *ptr;
struct iovec iovec; struct iovec iovec;
ret = renderer.input->read(renderer.input, thdr_buf, ret = ctx->input->read(ctx->input, thdr_buf,
VCMD_TRANSFER_HDR_SIZE * 4); VCMD_TRANSFER_HDR_SIZE * 4);
if (ret != VCMD_TRANSFER_HDR_SIZE * 4) { if (ret != VCMD_TRANSFER_HDR_SIZE * 4) {
return ret; return ret;
} }
@ -739,7 +745,7 @@ int vtest_transfer_get(UNUSED uint32_t length_dw)
fprintf(stderr," transfer read failed %d\n", ret); fprintf(stderr," transfer read failed %d\n", ret);
} }
ret = vtest_block_write(renderer.out_fd, ptr, data_size); ret = vtest_block_write(ctx->out_fd, ptr, data_size);
free(ptr); free(ptr);
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
@ -747,6 +753,7 @@ int vtest_transfer_get(UNUSED uint32_t length_dw)
int vtest_transfer_get_nop(UNUSED uint32_t length_dw) int vtest_transfer_get_nop(UNUSED uint32_t length_dw)
{ {
struct vtest_context *ctx = vtest_get_current_context();
uint32_t thdr_buf[VCMD_TRANSFER_HDR_SIZE]; uint32_t thdr_buf[VCMD_TRANSFER_HDR_SIZE];
int ret; int ret;
UNUSED int level; UNUSED int level;
@ -755,8 +762,8 @@ int vtest_transfer_get_nop(UNUSED uint32_t length_dw)
uint32_t data_size; uint32_t data_size;
void *ptr; void *ptr;
ret = renderer.input->read(renderer.input, thdr_buf, ret = ctx->input->read(ctx->input, thdr_buf,
VCMD_TRANSFER_HDR_SIZE * 4); VCMD_TRANSFER_HDR_SIZE * 4);
if (ret != VCMD_TRANSFER_HDR_SIZE * 4) { if (ret != VCMD_TRANSFER_HDR_SIZE * 4) {
return ret; return ret;
} }
@ -774,7 +781,7 @@ int vtest_transfer_get_nop(UNUSED uint32_t length_dw)
memset(ptr, 0, data_size); memset(ptr, 0, data_size);
ret = vtest_block_write(renderer.out_fd, ptr, data_size); ret = vtest_block_write(ctx->out_fd, ptr, data_size);
free(ptr); free(ptr);
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
@ -792,8 +799,8 @@ int vtest_transfer_put(UNUSED uint32_t length_dw)
void *ptr; void *ptr;
struct iovec iovec; struct iovec iovec;
ret = renderer.input->read(renderer.input, thdr_buf, ret = ctx->input->read(ctx->input, thdr_buf,
VCMD_TRANSFER_HDR_SIZE * 4); VCMD_TRANSFER_HDR_SIZE * 4);
if (ret != VCMD_TRANSFER_HDR_SIZE * 4) { if (ret != VCMD_TRANSFER_HDR_SIZE * 4) {
return ret; return ret;
} }
@ -809,7 +816,7 @@ int vtest_transfer_put(UNUSED uint32_t length_dw)
return -ENOMEM; return -ENOMEM;
} }
ret = renderer.input->read(renderer.input, ptr, data_size); ret = ctx->input->read(ctx->input, ptr, data_size);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -834,6 +841,7 @@ int vtest_transfer_put(UNUSED uint32_t length_dw)
int vtest_transfer_put_nop(UNUSED uint32_t length_dw) int vtest_transfer_put_nop(UNUSED uint32_t length_dw)
{ {
struct vtest_context *ctx = vtest_get_current_context();
uint32_t thdr_buf[VCMD_TRANSFER_HDR_SIZE]; uint32_t thdr_buf[VCMD_TRANSFER_HDR_SIZE];
int ret; int ret;
UNUSED int level; UNUSED int level;
@ -842,8 +850,8 @@ int vtest_transfer_put_nop(UNUSED uint32_t length_dw)
uint32_t data_size; uint32_t data_size;
void *ptr; void *ptr;
ret = renderer.input->read(renderer.input, thdr_buf, ret = ctx->input->read(ctx->input, thdr_buf,
VCMD_TRANSFER_HDR_SIZE * 4); VCMD_TRANSFER_HDR_SIZE * 4);
if (ret != VCMD_TRANSFER_HDR_SIZE * 4) { if (ret != VCMD_TRANSFER_HDR_SIZE * 4) {
return ret; return ret;
} }
@ -859,7 +867,7 @@ int vtest_transfer_put_nop(UNUSED uint32_t length_dw)
return -ENOMEM; return -ENOMEM;
} }
ret = renderer.input->read(renderer.input, ptr, data_size); ret = ctx->input->read(ctx->input, ptr, data_size);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -894,7 +902,7 @@ int vtest_transfer_get2(UNUSED uint32_t length_dw)
uint32_t offset; uint32_t offset;
struct iovec *iovec; struct iovec *iovec;
ret = renderer.input->read(renderer.input, thdr_buf, sizeof(thdr_buf)); ret = ctx->input->read(ctx->input, thdr_buf, sizeof(thdr_buf));
if (ret != sizeof(thdr_buf)) { if (ret != sizeof(thdr_buf)) {
return ret; return ret;
} }
@ -927,6 +935,7 @@ int vtest_transfer_get2(UNUSED uint32_t length_dw)
int vtest_transfer_get2_nop(UNUSED uint32_t length_dw) int vtest_transfer_get2_nop(UNUSED uint32_t length_dw)
{ {
struct vtest_context *ctx = vtest_get_current_context();
uint32_t thdr_buf[VCMD_TRANSFER2_HDR_SIZE]; uint32_t thdr_buf[VCMD_TRANSFER2_HDR_SIZE];
int ret; int ret;
UNUSED int level; UNUSED int level;
@ -935,7 +944,7 @@ int vtest_transfer_get2_nop(UNUSED uint32_t length_dw)
uint32_t offset; uint32_t offset;
struct iovec *iovec; struct iovec *iovec;
ret = renderer.input->read(renderer.input, thdr_buf, sizeof(thdr_buf)); ret = ctx->input->read(ctx->input, thdr_buf, sizeof(thdr_buf));
if (ret != sizeof(thdr_buf)) { if (ret != sizeof(thdr_buf)) {
return ret; return ret;
} }
@ -966,7 +975,7 @@ int vtest_transfer_put2(UNUSED uint32_t length_dw)
uint32_t offset; uint32_t offset;
struct iovec *iovec; struct iovec *iovec;
ret = renderer.input->read(renderer.input, thdr_buf, sizeof(thdr_buf)); ret = ctx->input->read(ctx->input, thdr_buf, sizeof(thdr_buf));
if (ret != sizeof(thdr_buf)) { if (ret != sizeof(thdr_buf)) {
return ret; return ret;
} }
@ -995,6 +1004,7 @@ int vtest_transfer_put2(UNUSED uint32_t length_dw)
int vtest_transfer_put2_nop(UNUSED uint32_t length_dw) int vtest_transfer_put2_nop(UNUSED uint32_t length_dw)
{ {
struct vtest_context *ctx = vtest_get_current_context();
uint32_t thdr_buf[VCMD_TRANSFER2_HDR_SIZE]; uint32_t thdr_buf[VCMD_TRANSFER2_HDR_SIZE];
int ret; int ret;
UNUSED int level; UNUSED int level;
@ -1004,7 +1014,7 @@ int vtest_transfer_put2_nop(UNUSED uint32_t length_dw)
UNUSED uint32_t offset; UNUSED uint32_t offset;
struct iovec *iovec; struct iovec *iovec;
ret = renderer.input->read(renderer.input, thdr_buf, sizeof(thdr_buf)); ret = ctx->input->read(ctx->input, thdr_buf, sizeof(thdr_buf));
if (ret != sizeof(thdr_buf)) { if (ret != sizeof(thdr_buf)) {
return ret; return ret;
} }
@ -1021,6 +1031,7 @@ int vtest_transfer_put2_nop(UNUSED uint32_t length_dw)
int vtest_resource_busy_wait(UNUSED uint32_t length_dw) int vtest_resource_busy_wait(UNUSED uint32_t length_dw)
{ {
struct vtest_context *ctx = vtest_get_current_context();
uint32_t bw_buf[VCMD_BUSY_WAIT_SIZE]; uint32_t bw_buf[VCMD_BUSY_WAIT_SIZE];
int ret, fd; int ret, fd;
int flags; int flags;
@ -1028,7 +1039,7 @@ int vtest_resource_busy_wait(UNUSED uint32_t length_dw)
uint32_t reply_buf[1]; uint32_t reply_buf[1];
bool busy = false; bool busy = false;
ret = renderer.input->read(renderer.input, &bw_buf, sizeof(bw_buf)); ret = ctx->input->read(ctx->input, &bw_buf, sizeof(bw_buf));
if (ret != sizeof(bw_buf)) { if (ret != sizeof(bw_buf)) {
return -1; return -1;
} }
@ -1059,12 +1070,12 @@ int vtest_resource_busy_wait(UNUSED uint32_t length_dw)
hdr_buf[VTEST_CMD_ID] = VCMD_RESOURCE_BUSY_WAIT; hdr_buf[VTEST_CMD_ID] = VCMD_RESOURCE_BUSY_WAIT;
reply_buf[0] = busy ? 1 : 0; reply_buf[0] = busy ? 1 : 0;
ret = vtest_block_write(renderer.out_fd, hdr_buf, sizeof(hdr_buf)); ret = vtest_block_write(ctx->out_fd, hdr_buf, sizeof(hdr_buf));
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
ret = vtest_block_write(renderer.out_fd, reply_buf, sizeof(reply_buf)); ret = vtest_block_write(ctx->out_fd, reply_buf, sizeof(reply_buf));
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }

@ -404,9 +404,9 @@ static void vtest_main_run_renderer(int in_fd, int out_fd,
break; break;
} }
ret = vtest_init_renderer(input, out_fd, ctx_flags, render_device); ret = vtest_init_renderer(ctx_flags, render_device);
if (ret >= 0) { if (ret >= 0) {
ret = vtest_create_context(header[0], &prog.context); ret = vtest_create_context(input, out_fd, header[0], &prog.context);
} }
if (ret < 0) { if (ret < 0) {
err = 4; err = 4;

Loading…
Cancel
Save