|
16 | 16 | #include <linux/fs.h> |
17 | 17 | #include <linux/anon_inodes.h> |
18 | 18 | #include <linux/mman.h> |
| 19 | +#include <linux/pid_namespace.h> |
19 | 20 |
|
20 | 21 | #include "dxgkrnl.h" |
21 | 22 | #include "dxgvmbus.h" |
@@ -5238,6 +5239,85 @@ dxgkio_share_object_with_host(struct dxgprocess *process, void *__user inargs) |
5238 | 5239 | return ret; |
5239 | 5240 | } |
5240 | 5241 |
|
| 5242 | +static int |
| 5243 | +dxgkio_enum_processes(struct dxgprocess *process, void *__user inargs) |
| 5244 | +{ |
| 5245 | + struct d3dkmt_enumprocesses args; |
| 5246 | + struct d3dkmt_enumprocesses *__user input = inargs; |
| 5247 | + struct dxgadapter *adapter = NULL; |
| 5248 | + struct dxgadapter *entry; |
| 5249 | + struct dxgglobal *dxgglobal = dxggbl(); |
| 5250 | + struct dxgprocess_adapter *pentry; |
| 5251 | + int nump = 0; /* Current number of processes*/ |
| 5252 | + struct ntstatus status; |
| 5253 | + int ret; |
| 5254 | + |
| 5255 | + ret = copy_from_user(&args, inargs, sizeof(args)); |
| 5256 | + if (ret) { |
| 5257 | + DXG_ERR("failed to copy input args"); |
| 5258 | + ret = -EFAULT; |
| 5259 | + goto cleanup; |
| 5260 | + } |
| 5261 | + |
| 5262 | + if (args.buffer_count == 0) { |
| 5263 | + DXG_ERR("Invalid buffer count"); |
| 5264 | + ret = -EINVAL; |
| 5265 | + goto cleanup; |
| 5266 | + } |
| 5267 | + |
| 5268 | + dxgglobal_acquire_adapter_list_lock(DXGLOCK_SHARED); |
| 5269 | + dxgglobal_acquire_process_adapter_lock(); |
| 5270 | + |
| 5271 | + list_for_each_entry(entry, &dxgglobal->adapter_list_head, |
| 5272 | + adapter_list_entry) { |
| 5273 | + if (*(u64 *) &entry->luid == *(u64 *) &args.adapter_luid) { |
| 5274 | + adapter = entry; |
| 5275 | + break; |
| 5276 | + } |
| 5277 | + } |
| 5278 | + |
| 5279 | + if (adapter == NULL) { |
| 5280 | + DXG_ERR("Failed to find dxgadapter"); |
| 5281 | + ret = -EINVAL; |
| 5282 | + goto cleanup_locks; |
| 5283 | + } |
| 5284 | + |
| 5285 | + list_for_each_entry(pentry, &adapter->adapter_process_list_head, |
| 5286 | + adapter_process_list_entry) { |
| 5287 | + if (pentry->process->nspid != task_active_pid_ns(current)) |
| 5288 | + continue; |
| 5289 | + if (nump == args.buffer_count) { |
| 5290 | + status.v = STATUS_BUFFER_TOO_SMALL; |
| 5291 | + ret = ntstatus2int(status); |
| 5292 | + goto cleanup_locks; |
| 5293 | + } |
| 5294 | + ret = copy_to_user(&args.buffer[nump], &pentry->process->vpid, |
| 5295 | + sizeof(u32)); |
| 5296 | + if (ret) { |
| 5297 | + DXG_ERR("failed to copy data to user"); |
| 5298 | + ret = -EFAULT; |
| 5299 | + goto cleanup_locks; |
| 5300 | + } |
| 5301 | + nump++; |
| 5302 | + } |
| 5303 | + |
| 5304 | +cleanup_locks: |
| 5305 | + |
| 5306 | + dxgglobal_release_process_adapter_lock(); |
| 5307 | + dxgglobal_release_adapter_list_lock(DXGLOCK_SHARED); |
| 5308 | + |
| 5309 | + if (ret == 0) { |
| 5310 | + ret = copy_to_user(&input->buffer_count, &nump, sizeof(u32)); |
| 5311 | + if (ret) |
| 5312 | + DXG_ERR("failed to copy buffer count to user"); |
| 5313 | + } |
| 5314 | + |
| 5315 | +cleanup: |
| 5316 | + |
| 5317 | + DXG_TRACE_IOCTL_END(ret); |
| 5318 | + return ret; |
| 5319 | +} |
| 5320 | + |
5241 | 5321 | static struct ioctl_desc ioctls[] = { |
5242 | 5322 | /* 0x00 */ {}, |
5243 | 5323 | /* 0x01 */ {dxgkio_open_adapter_from_luid, LX_DXOPENADAPTERFROMLUID}, |
@@ -5325,6 +5405,7 @@ static struct ioctl_desc ioctls[] = { |
5325 | 5405 | /* 0x46 */ {dxgkio_wait_sync_file, LX_DXWAITSYNCFILE}, |
5326 | 5406 | /* 0x47 */ {dxgkio_open_syncobj_from_syncfile, |
5327 | 5407 | LX_DXOPENSYNCOBJECTFROMSYNCFILE}, |
| 5408 | +/* 0x48 */ {dxgkio_enum_processes, LX_DXENUMPROCESSES}, |
5328 | 5409 | }; |
5329 | 5410 |
|
5330 | 5411 | /* |
|
0 commit comments