From nobody Mon Apr 6 10:41:59 2026 Received: from mail-wm1-f42.google.com (mail-wm1-f42.google.com [209.85.128.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F073D3FEB17 for ; Thu, 19 Mar 2026 20:26:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773951969; cv=none; b=Aj3Fo5a37exuQ8bBLA+pW7e0RVqRAnbv0K/88HAmyuYyE1yvzz1KcpMdPUMbYU7ZLWL1VZvvBUGQEu5edkiU2xclKy7knhegKShNREAbyXEemmaeNe+POHTZqWMuO81xEKGX3BpBmYG62wG0NGhUFpZ73t/9ksiCBbtgDDkHMTQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773951969; c=relaxed/simple; bh=Z4PYI3Irnqgd469D+z9UfdlrSw8gbWCsjEqZiiqnGOc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=B9lSlhIvRGp5aedV8nqaqGuxs59XqjGAJKIu94MJgOrtEUFow8GZrg3hvJcwHZfsgKau99ngL3Mv5I2j9Pfiigt1FftAo3cU7HpyeBnXQnTaBRtLZ86uv3KcTOGzppCWYxKh5qMaQzcrs5oyIwN9WRgPH3COWOwWoTEI2CfZCqo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=YgPi6iKA; arc=none smtp.client-ip=209.85.128.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="YgPi6iKA" Received: by mail-wm1-f42.google.com with SMTP id 5b1f17b1804b1-485392de558so9141165e9.1 for ; Thu, 19 Mar 2026 13:26:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773951962; x=1774556762; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=z6+n+f//BdkXFe0SxztsrgegLDZqmvdOMqnM0EvvH8Y=; b=YgPi6iKAAyEd6ZDihlMD8u7aPvOmJpI/t/EbvwSc0/YaNsSisFnEL8ZoZt8DMRI3Xv LDhV5wvYHKfsdv+u/0CNdEL8LylPPxP7Meb/GRtMonr9XS8v7R5B+SyBLAu/P/9v0zhv zHja+uDJgWlYpTkq6ItJB/K3ky3nKLtmXzRL5Wzcuu0VaKvb2KhwPx6cqCAZ/yZJQBNE 5mrYzb0KN9EKyDHtK5Wv596Dg9SSuDHkSB4+owMt1m3kVVYxpesaEUxV7FjXBV58NYHM Gi5rTyMWMq/6ygCBNPShwbvdvIkMhLGRZaL2HdRNW+Nkk0Cd9kbUnlbAmdItjteTXTrD DW9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773951962; x=1774556762; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=z6+n+f//BdkXFe0SxztsrgegLDZqmvdOMqnM0EvvH8Y=; b=fLlQ2D3YQaUOeueLyZU2LnFNNqSexmnvP2EnQhDBFTcoO7UtEGCI7AXAkd9p/8YK15 FxzJk/OXaiTBz5PX7J7F6ntj0AD2kQ1RsmOin22UajhJGuwkjKvSj3EwBw5qoVU4IBfT a3R9eDmSuzDSFe0vncmitT+z0V9SPDMuLz3ok+e5PlQJYQcB0wFkBcw8cZqmEOjqdM5v yGzGres0ixkKDk831UELr2Yye/5cmKh6SaWBFhrghUWA28ZtSZatgUaX+4WIModzpEcc qP9zaO+6IDlvzzUV0nrOjIq4sgnmK9r1yNsk6JEoLWjikiUC7hTSH5egT0GYj2tismh0 H57w== X-Gm-Message-State: AOJu0YzQxyf/OwS0ZruvQtBA9KltVTwTdXmH+GNAAmrA45/ZN9of2Npr wQgFMKHmcU06XulBI8UiqgeieAUfWT3idQoJBK3aZkVgwYWSBS5WaspsyFpa62HT8Og= X-Gm-Gg: ATEYQzx3ooqw0H8PacMxazHcVKzlmxW09m402/BLU7vDICF/SOt4rbrxYsKX9E72jNM ZksxS1YVtfVFtmkrV7lSUDSFIxKCW2l8UbgO6Ya3nBUZ/vVz4lNGFoQv90Wmo9ynpzAkLwNmKVe I4p9kD1tiEbXUkaMAMM/xBouArc9a/6dmMpiDmDx7hbaEqb7QDQ13vedRsVwxLZPYojMbkfsgJO foJyR4wh6NKLB/byW+/JsV6CpGTSR6SKQgaDpPQkQwgX72WMwgPt6DUcpxzSlLKluebS9ks7HBx RuTimA6wu/mNezIDIreu6UZ9NppyryFwOPnos9Yz7RpXejgUkvQw7p3+Rr3oNB70RKrdppL1/xR 0wFn8mgtVWDRDaYTCPibRCBfi09BzKncQxBVwmnjcCwWlwJ/pODMyqjvO8J+RqPrVSoyXxHP3zW 6j+Mzg2swzuhOnG8VFIw8eq2n0OyDONligdRniY/xOA+KeKTX1 X-Received: by 2002:a05:600c:348c:b0:485:39b2:a47c with SMTP id 5b1f17b1804b1-486fee1af1cmr6282575e9.25.1773951961862; Thu, 19 Mar 2026 13:26:01 -0700 (PDT) Received: from LQ5W56KC4T ([2001:8a0:672f:7800:e0e1:55cd:f0b:b1e5]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-43b644ae16fsm1347544f8f.8.2026.03.19.13.26.00 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 19 Mar 2026 13:26:01 -0700 (PDT) From: Eric Curtin X-Google-Original-From: Eric Curtin To: linux-hyperv@vger.kernel.org Cc: linux-kernel@vger.kernel.org, iourit@linux.microsoft.com, wei.liu@kernel.org, decui@microsoft.com, haiyangz@microsoft.com Subject: [PATCH 43/55] drivers: hv: dxgkrnl: Implement D3DDKMTIsFeatureEnabled API Date: Thu, 19 Mar 2026 20:24:57 +0000 Message-ID: <20260319202509.63802-44-eric.curtin@docker.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com> References: <20260319202509.63802-1-eric.curtin@docker.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Iouri Tarassov D3DKMTIsFeatureEnabled is used to query if a particular feature is supported by the given adapter. Signed-off-by: Iouri Tarassov [kms: forward port to 6.6 from 6.1. No code changes made.] Signed-off-by: Kelsey Steele --- drivers/hv/dxgkrnl/dxgkrnl.h | 2 ++ drivers/hv/dxgkrnl/dxgvmbus.c | 58 ++++++++++++++++++++++++++++++++--- drivers/hv/dxgkrnl/dxgvmbus.h | 31 +++++++++++++++++++ drivers/hv/dxgkrnl/ioctl.c | 46 +++++++++++++++++++++++++++ include/uapi/misc/d3dkmthk.h | 31 ++++++++++++++++++- 5 files changed, 163 insertions(+), 5 deletions(-) diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h index 90bcd5377744..ebf81cffa289 100644 --- a/drivers/hv/dxgkrnl/dxgkrnl.h +++ b/drivers/hv/dxgkrnl/dxgkrnl.h @@ -994,6 +994,8 @@ int dxgvmb_send_share_object_with_host(struct dxgproces= s *process, int dxgvmb_send_invalidate_cache(struct dxgprocess *process, struct dxgadapter *adapter, struct d3dkmt_invalidatecache *args); +int dxgvmb_send_is_feature_enabled(struct dxgadapter *adapter, + struct d3dkmt_isfeatureenabled *args); =20 void signal_host_cpu_event(struct dxghostevent *eventhdr); int ntstatus2int(struct ntstatus status); diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c index 916ed9071656..2436e1a7bc73 100644 --- a/drivers/hv/dxgkrnl/dxgvmbus.c +++ b/drivers/hv/dxgkrnl/dxgvmbus.c @@ -135,15 +135,16 @@ static int init_message_res(struct dxgvmbusmsgres *ms= g, if (use_ext_header) { msg->msg =3D (char *)&msg->hdr[1]; msg->hdr->command_offset =3D sizeof(msg->hdr[0]); - msg->hdr->vgpu_luid =3D adapter->host_vgpu_luid; + if (adapter) + msg->hdr->vgpu_luid =3D adapter->host_vgpu_luid; } else { msg->msg =3D (char *)msg->hdr; } msg->res =3D (char *)msg->hdr + msg->size; - if (dxgglobal->async_msg_enabled) - msg->channel =3D &dxgglobal->channel; - else + if (adapter && !dxgglobal->async_msg_enabled) msg->channel =3D &adapter->channel; + else + msg->channel =3D &dxgglobal->channel; return 0; } =20 @@ -2049,6 +2050,55 @@ int dxgvmb_send_invalidate_cache(struct dxgprocess *= process, return ret; } =20 +int dxgvmb_send_is_feature_enabled(struct dxgadapter *adapter, + struct d3dkmt_isfeatureenabled *args) +{ + int ret; + struct dxgkvmb_command_isfeatureenabled_return *result; + struct dxgvmbusmsgres msg =3D {.hdr =3D NULL}; + int res_size =3D sizeof(*result); + + if (adapter) { + struct dxgkvmb_command_isfeatureenabled *command; + + ret =3D init_message_res(&msg, adapter, sizeof(*command), + res_size); + if (ret) + goto cleanup; + command =3D (void *)msg.msg; + command->feature_id =3D args->feature_id; + result =3D msg.res; + command_vgpu_to_host_init1(&command->hdr, + DXGK_VMBCOMMAND_ISFEATUREENABLED); + } else { + struct dxgkvmb_command_isfeatureenabled_gbl *command; + + ret =3D init_message_res(&msg, adapter, sizeof(*command), + res_size); + if (ret) + goto cleanup; + command =3D (void *)msg.msg; + command->feature_id =3D args->feature_id; + result =3D msg.res; + command_vm_to_host_init1(&command->hdr, + DXGK_VMBCOMMAND_ISFEATUREENABLED_GLOBAL); + } + ret =3D dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size, + result, res_size); + if (ret =3D=3D 0) { + ret =3D ntstatus2int(result->status); + if (ret =3D=3D 0) + args->result =3D result->result; + goto cleanup; + } + +cleanup: + free_message((struct dxgvmbusmsg *)&msg); + if (ret) + DXG_TRACE("err: %d", ret); + return ret; +} + int dxgvmb_send_query_alloc_residency(struct dxgprocess *process, struct dxgadapter *adapter, struct d3dkmt_queryallocationresidency diff --git a/drivers/hv/dxgkrnl/dxgvmbus.h b/drivers/hv/dxgkrnl/dxgvmbus.h index 20c562b485de..a7e625b2f896 100644 --- a/drivers/hv/dxgkrnl/dxgvmbus.h +++ b/drivers/hv/dxgkrnl/dxgvmbus.h @@ -48,6 +48,7 @@ enum dxgkvmb_commandtype_global { DXGK_VMBCOMMAND_SETIOSPACEREGION =3D 1010, DXGK_VMBCOMMAND_COMPLETETRANSACTION =3D 1011, DXGK_VMBCOMMAND_SHAREOBJECTWITHHOST =3D 1021, + DXGK_VMBCOMMAND_ISFEATUREENABLED_GLOBAL =3D 1022, DXGK_VMBCOMMAND_INVALID_VM_TO_HOST }; =20 @@ -126,6 +127,7 @@ enum dxgkvmb_commandtype { DXGK_VMBCOMMAND_LOGEVENT =3D 65, DXGK_VMBCOMMAND_SETEXISTINGSYSMEMPAGES =3D 66, DXGK_VMBCOMMAND_INVALIDATECACHE =3D 67, + DXGK_VMBCOMMAND_ISFEATUREENABLED =3D 68, DXGK_VMBCOMMAND_INVALID }; =20 @@ -871,6 +873,35 @@ struct dxgkvmb_command_shareobjectwithhost_return { u64 vail_nt_handle; }; =20 +struct dxgk_feature_desc { + u16 min_supported_version; + u16 max_supported_version; + struct { + u16 supported : 1; + u16 virtualization_mode : 3; + u16 global : 1; + u16 driver_feature : 1; + u16 internal : 1; + u16 reserved : 9; + }; +}; + +struct dxgkvmb_command_isfeatureenabled { + struct dxgkvmb_command_vgpu_to_host hdr; + enum dxgk_feature_id feature_id; +}; + +struct dxgkvmb_command_isfeatureenabled_gbl { + struct dxgkvmb_command_vm_to_host hdr; + enum dxgk_feature_id feature_id; +}; + +struct dxgkvmb_command_isfeatureenabled_return { + struct ntstatus status; + struct dxgk_feature_desc descriptor; + struct dxgk_isfeatureenabled_result result; +}; + int dxgvmb_send_sync_msg(struct dxgvmbuschannel *channel, void *command, u32 command_size, void *result, diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c index 24b84be2fb73..5ff4b27af19d 100644 --- a/drivers/hv/dxgkrnl/ioctl.c +++ b/drivers/hv/dxgkrnl/ioctl.c @@ -5318,6 +5318,51 @@ dxgkio_enum_processes(struct dxgprocess *process, vo= id *__user inargs) return ret; } =20 +static int +dxgkio_is_feature_enabled(struct dxgprocess *process, void *__user inargs) +{ + struct d3dkmt_isfeatureenabled args; + struct dxgadapter *adapter =3D NULL; + struct dxgglobal *dxgglobal =3D dxggbl(); + struct d3dkmt_isfeatureenabled *__user uargs =3D inargs; + int ret; + + ret =3D copy_from_user(&args, inargs, sizeof(args)); + if (ret) { + DXG_ERR("failed to copy input args"); + ret =3D -EFAULT; + goto cleanup; + } + + adapter =3D dxgprocess_adapter_by_handle(process, args.adapter); + if (adapter =3D=3D NULL) { + ret =3D -EINVAL; + goto cleanup; + } + + if (adapter) { + ret =3D dxgadapter_acquire_lock_shared(adapter); + if (ret < 0) + goto cleanup; + } + + ret =3D dxgvmb_send_is_feature_enabled(adapter, &args); + if (ret) + goto cleanup; + + ret =3D copy_to_user(&uargs->result, &args.result, sizeof(args.result)); + +cleanup: + + if (adapter) { + dxgadapter_release_lock_shared(adapter); + kref_put(&adapter->adapter_kref, dxgadapter_release); + } + + DXG_TRACE_IOCTL_END(ret); + return ret; +} + static struct ioctl_desc ioctls[] =3D { /* 0x00 */ {}, /* 0x01 */ {dxgkio_open_adapter_from_luid, LX_DXOPENADAPTERFROMLUID}, @@ -5406,6 +5451,7 @@ static struct ioctl_desc ioctls[] =3D { /* 0x47 */ {dxgkio_open_syncobj_from_syncfile, LX_DXOPENSYNCOBJECTFROMSYNCFILE}, /* 0x48 */ {dxgkio_enum_processes, LX_DXENUMPROCESSES}, +/* 0x49 */ {dxgkio_is_feature_enabled, LX_ISFEATUREENABLED}, }; =20 /* diff --git a/include/uapi/misc/d3dkmthk.h b/include/uapi/misc/d3dkmthk.h index f9f817060fa9..5b345ddaf66e 100644 --- a/include/uapi/misc/d3dkmthk.h +++ b/include/uapi/misc/d3dkmthk.h @@ -1580,7 +1580,7 @@ struct d3dkmt_opensyncobjectfromsyncfile { __u64 fence_value_gpu_va; /* out */ }; =20 - struct d3dkmt_enumprocesses { +struct d3dkmt_enumprocesses { struct winluid adapter_luid; #ifdef __KERNEL__ __u32 *buffer; @@ -1590,6 +1590,33 @@ struct d3dkmt_opensyncobjectfromsyncfile { __u64 buffer_count; }; =20 +enum dxgk_feature_id { + _DXGK_FEATURE_HWSCH =3D 0, + _DXGK_FEATURE_PAGE_BASED_MEMORY_MANAGER =3D 32, + _DXGK_FEATURE_KERNEL_MODE_TESTING =3D 33, + _DXGK_FEATURE_MAX +}; + +struct dxgk_isfeatureenabled_result { + __u16 version; + union { + struct { + __u16 enabled : 1; + __u16 known_feature : 1; + __u16 supported_by_driver : 1; + __u16 supported_on_config : 1; + __u16 reserved : 12; + }; + __u16 value; + }; +}; + +struct d3dkmt_isfeatureenabled { + struct d3dkmthandle adapter; + enum dxgk_feature_id feature_id; + struct dxgk_isfeatureenabled_result result; +}; + struct d3dkmt_invalidatecache { struct d3dkmthandle device; struct d3dkmthandle allocation; @@ -1730,5 +1757,7 @@ struct d3dkmt_invalidatecache { _IOWR(0x47, 0x47, struct d3dkmt_opensyncobjectfromsyncfile) #define LX_DXENUMPROCESSES \ _IOWR(0x47, 0x48, struct d3dkmt_enumprocesses) +#define LX_ISFEATUREENABLED \ + _IOWR(0x47, 0x49, struct d3dkmt_isfeatureenabled) =20 #endif /* _D3DKMTHK_H */