1 /*
2 * Copyright 2020 Google LLC
3 * SPDX-License-Identifier: MIT
4 */
5
6 #ifndef VKR_CONTEXT_H
7 #define VKR_CONTEXT_H
8
9 #include "vkr_common.h"
10
11 #include "venus-protocol/vn_protocol_renderer_defines.h"
12 #include "virgl_context.h"
13
14 #include "vkr_cs.h"
15
16 struct virgl_resource;
17
18 /*
19 * When a virgl_resource is attached in vkr_context_attach_resource, a
20 * vkr_resource_attachment is created. A vkr_resource_attachment is valid
21 * until the resource it tracks is detached.
22 *
23 * To support transfers to resources not backed by coherent dma-bufs, we
24 * associate a vkr_resource_attachment with a (list of) vkr_device_memory.
25 * This way, we can find a vkr_device_memory from a vkr_resource_attachment
26 * and do transfers using VkDeviceMemory.
27 */
28 struct vkr_resource_attachment {
29 struct virgl_resource *resource;
30 struct list_head memories;
31 };
32
33 enum vkr_context_validate_level {
34 /* no validation */
35 VKR_CONTEXT_VALIDATE_NONE,
36 /* force enabling a subset of the validation layer */
37 VKR_CONTEXT_VALIDATE_ON,
38 /* force enabling the validation layer */
39 VKR_CONTEXT_VALIDATE_FULL,
40 };
41
42 struct vkr_context {
43 struct virgl_context base;
44
45 char *debug_name;
46 enum vkr_context_validate_level validate_level;
47 bool validate_fatal;
48
49 mtx_t mutex;
50
51 struct list_head rings;
52 struct util_hash_table_u64 *object_table;
53 struct util_hash_table *resource_table;
54 struct list_head newly_exported_memories;
55
56 struct vkr_cs_encoder encoder;
57 struct vkr_cs_decoder decoder;
58 struct vn_dispatch_context dispatch;
59
60 int fence_eventfd;
61 struct list_head busy_queues;
62 struct list_head signaled_syncs;
63
64 struct vkr_instance *instance;
65 char *instance_name;
66 };
67
68 static inline bool
vkr_context_validate_object_id(struct vkr_context * ctx,vkr_object_id id)69 vkr_context_validate_object_id(struct vkr_context *ctx, vkr_object_id id)
70 {
71 if (unlikely(!id || util_hash_table_get_u64(ctx->object_table, id))) {
72 vkr_cs_decoder_set_fatal(&ctx->decoder);
73 return false;
74 }
75
76 return true;
77 }
78
79 static inline void *
vkr_context_alloc_object(UNUSED struct vkr_context * ctx,size_t size,VkObjectType type,const void * id_handle)80 vkr_context_alloc_object(UNUSED struct vkr_context *ctx,
81 size_t size,
82 VkObjectType type,
83 const void *id_handle)
84 {
85 const vkr_object_id id = vkr_cs_handle_load_id((const void **)id_handle, type);
86 if (!vkr_context_validate_object_id(ctx, id))
87 return NULL;
88
89 return vkr_object_alloc(size, type, id);
90 }
91
92 static inline void
vkr_context_add_object(struct vkr_context * ctx,struct vkr_object * obj)93 vkr_context_add_object(struct vkr_context *ctx, struct vkr_object *obj)
94 {
95 assert(vkr_is_recognized_object_type(obj->type));
96 assert(obj->id);
97 assert(!util_hash_table_get_u64(ctx->object_table, obj->id));
98
99 util_hash_table_set_u64(ctx->object_table, obj->id, obj);
100 }
101
102 static inline void
vkr_context_remove_object(struct vkr_context * ctx,struct vkr_object * obj)103 vkr_context_remove_object(struct vkr_context *ctx, struct vkr_object *obj)
104 {
105 assert(util_hash_table_get_u64(ctx->object_table, obj->id));
106
107 /* this frees obj */
108 util_hash_table_remove_u64(ctx->object_table, obj->id);
109 }
110
111 static inline void
vkr_context_remove_objects(struct vkr_context * ctx,struct list_head * objects)112 vkr_context_remove_objects(struct vkr_context *ctx, struct list_head *objects)
113 {
114 struct vkr_object *obj, *tmp;
115 LIST_FOR_EACH_ENTRY_SAFE (obj, tmp, objects, track_head)
116 vkr_context_remove_object(ctx, obj);
117 /* objects should be reinitialized if to be reused */
118 }
119
120 static inline const char *
vkr_context_get_name(const struct vkr_context * ctx)121 vkr_context_get_name(const struct vkr_context *ctx)
122 {
123 /* ctx->instance_name is the application name while ctx->debug_name is
124 * usually the guest process name or the hypervisor name. This never
125 * returns NULL because ctx->debug_name is never NULL.
126 */
127 return ctx->instance_name ? ctx->instance_name : ctx->debug_name;
128 }
129
130 void
131 vkr_context_add_instance(struct vkr_context *ctx,
132 struct vkr_instance *instance,
133 const char *name);
134
135 void
136 vkr_context_remove_instance(struct vkr_context *ctx, struct vkr_instance *instance);
137
138 #endif /* VKR_CONTEXT_H */
139