]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/xe/pf: Restrict device query responses in admin-only PF mode
authorSatyanarayana K V P <satyanarayana.k.v.p@intel.com>
Thu, 9 Apr 2026 15:44:25 +0000 (15:44 +0000)
committerMichal Wajdeczko <michal.wajdeczko@intel.com>
Tue, 14 Apr 2026 10:38:14 +0000 (12:38 +0200)
When a PF is configured in admin-only mode, it is intended for management
only and must not expose workload-facing capabilities to userspace.

Limit the exposed ioctl set in admin-only PF mode to XE_DEVICE_QUERY and
XE_OBSERVATION, and suppress capability-bearing query payloads so that
the userspace cannot discover execution-related device details in this
mode.

Signed-off-by: Satyanarayana K V P <satyanarayana.k.v.p@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Piotr Piórkowski <piotr.piorkowski@intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Cc: Michał Winiarski <michal.winiarski@intel.com>
Cc: Dunajski Bartosz <bartosz.dunajski@intel.com>
Cc: Ashutosh Dixit <ashutosh.dixit@intel.com>
Cc: dri-devel@lists.freedesktop.org
Acked-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Acked-by: Ashutosh Dixit <ashutosh.dixit@intel.com>
Reviewed-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Link: https://patch.msgid.link/20260409154423.2499340-5-satyanarayana.k.v.p@intel.com
drivers/gpu/drm/xe/xe_device.c
drivers/gpu/drm/xe/xe_device.h
drivers/gpu/drm/xe/xe_hw_engine.c
drivers/gpu/drm/xe/xe_query.c

index cbce1d0ffe4829675928dcb5d75839c2aa961474..ceddda10f78fe581051c875a47fe77bd85313691 100644 (file)
@@ -25,6 +25,7 @@
 #include "regs/xe_regs.h"
 #include "xe_bo.h"
 #include "xe_bo_evict.h"
+#include "xe_configfs.h"
 #include "xe_debugfs.h"
 #include "xe_defaults.h"
 #include "xe_devcoredump.h"
@@ -390,7 +391,7 @@ bool xe_is_xe_file(const struct file *file)
        return file->f_op == &xe_driver_fops;
 }
 
-static struct drm_driver driver = {
+static struct drm_driver regular_driver = {
        .driver_features =
            DRIVER_GEM |
            DRIVER_RENDER | DRIVER_SYNCOBJ |
@@ -415,6 +416,39 @@ static struct drm_driver driver = {
        .patchlevel = DRIVER_PATCHLEVEL,
 };
 
+#ifdef CONFIG_PCI_IOV
+static const struct drm_ioctl_desc xe_ioctls_admin_only[] = {
+       DRM_IOCTL_DEF_DRV(XE_DEVICE_QUERY, xe_query_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl, DRM_RENDER_ALLOW),
+};
+
+static struct drm_driver admin_only_driver = {
+       .driver_features =
+           DRIVER_GEM | DRIVER_RENDER | DRIVER_GEM_GPUVA,
+       .open = xe_file_open,
+       .postclose = xe_file_close,
+       .ioctls = xe_ioctls_admin_only,
+       .num_ioctls = ARRAY_SIZE(xe_ioctls_admin_only),
+       .fops = &xe_driver_fops,
+       .name = DRIVER_NAME,
+       .desc = DRIVER_DESC,
+       .major = DRIVER_MAJOR,
+       .minor = DRIVER_MINOR,
+       .patchlevel = DRIVER_PATCHLEVEL,
+};
+
+/**
+ * xe_device_is_admin_only() - Check whether device is admin only or not.
+ * @xe: the &xe_device to check
+ *
+ * Return: true if the device is admin only, false otherwise.
+ */
+bool xe_device_is_admin_only(const struct xe_device *xe)
+{
+       return xe->drm.driver == &admin_only_driver;
+}
+#endif
+
 static void xe_device_destroy(struct drm_device *dev, void *dummy)
 {
        struct xe_device *xe = to_xe_device(dev);
@@ -439,16 +473,26 @@ static void xe_device_destroy(struct drm_device *dev, void *dummy)
 struct xe_device *xe_device_create(struct pci_dev *pdev,
                                   const struct pci_device_id *ent)
 {
+       struct drm_driver *driver = &regular_driver;
        struct xe_device *xe;
        int err;
 
-       xe_display_driver_set_hooks(&driver);
+#ifdef CONFIG_PCI_IOV
+       /*
+        * Since XE device is not initialized yet, read from configfs
+        * directly to decide whether we are in admin-only PF mode or not.
+        */
+       if (xe_configfs_admin_only_pf(pdev))
+               driver = &admin_only_driver;
+#endif
+
+       xe_display_driver_set_hooks(driver);
 
-       err = aperture_remove_conflicting_pci_devices(pdev, driver.name);
+       err = aperture_remove_conflicting_pci_devices(pdev, driver->name);
        if (err)
                return ERR_PTR(err);
 
-       xe = devm_drm_dev_alloc(&pdev->dev, &driver, struct xe_device, drm);
+       xe = devm_drm_dev_alloc(&pdev->dev, driver, struct xe_device, drm);
        if (IS_ERR(xe))
                return xe;
 
@@ -708,6 +752,11 @@ int xe_device_probe_early(struct xe_device *xe)
 
        xe_sriov_probe_early(xe);
 
+       if (xe_device_is_admin_only(xe) && !IS_SRIOV_PF(xe)) {
+               xe_err(xe, "Can't run Admin-only mode without SR-IOV PF mode!\n");
+               return -ENODEV;
+       }
+
        if (IS_SRIOV_VF(xe))
                vf_update_device_info(xe);
 
index e4b9de8d8e95c8fe9b4b6461364ec94c1d110c54..555c191f75107c4d86dc63026e8f61eec0b1daf3 100644 (file)
@@ -211,6 +211,15 @@ bool xe_is_xe_file(const struct file *file);
 
 struct xe_vm *xe_device_asid_to_vm(struct xe_device *xe, u32 asid);
 
+#ifdef CONFIG_PCI_IOV
+bool xe_device_is_admin_only(const struct xe_device *xe);
+#else
+static inline bool xe_device_is_admin_only(const struct xe_device *xe)
+{
+       return false;
+}
+#endif
+
 /*
  * Occasionally it is seen that the G2H worker starts running after a delay of more than
  * a second even after being queued and activated by the Linux workqueue subsystem. This
index 6dd05fac659564b52adb36858c6082177a8e453f..2f9c1c063f16c7ced090c944144fdd2a9623e97e 100644 (file)
@@ -1026,6 +1026,9 @@ bool xe_hw_engine_is_reserved(struct xe_hw_engine *hwe)
        struct xe_gt *gt = hwe->gt;
        struct xe_device *xe = gt_to_xe(gt);
 
+       if (xe_device_is_admin_only(xe))
+               return true;
+
        if (hwe->class == XE_ENGINE_CLASS_OTHER)
                return true;
 
index d84d6a422c45d64969f6792220c9458c66a0a7e4..8c7d54498f3840cd6412c3163a8dd2386b6f6733 100644 (file)
@@ -231,6 +231,9 @@ static size_t calc_mem_regions_size(struct xe_device *xe)
        u32 num_managers = 1;
        int i;
 
+       if (xe_device_is_admin_only(xe))
+               return sizeof(struct drm_xe_query_mem_regions);
+
        for (i = XE_PL_VRAM0; i <= XE_PL_VRAM1; ++i)
                if (ttm_manager_type(&xe->ttm, i))
                        num_managers++;
@@ -259,6 +262,9 @@ static int query_mem_regions(struct xe_device *xe,
        if (XE_IOCTL_DBG(xe, !mem_regions))
                return -ENOMEM;
 
+       if (xe_device_is_admin_only(xe))
+               goto user_copy;
+
        man = ttm_manager_type(&xe->ttm, XE_PL_TT);
        mem_regions->mem_regions[0].mem_class = DRM_XE_MEM_REGION_CLASS_SYSMEM;
        /*
@@ -297,6 +303,7 @@ static int query_mem_regions(struct xe_device *xe,
                }
        }
 
+user_copy:
        if (!copy_to_user(query_ptr, mem_regions, size))
                ret = 0;
        else