diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
index 9c873c3912cc..13233fc87b53 100644
--- a/Documentation/gpu/vkms.rst
+++ b/Documentation/gpu/vkms.rst
@@ -51,6 +51,29 @@ To disable the driver, use ::
 
   sudo modprobe -r vkms
 
+Configuration With ConfigFS
+===========================
+
+VKMS is instrumented with support for configuration via `ConfigFS`. With VKMS
+installed, you can mount ConfigFS at /config/ like so::
+
+  mkdir -p /config/
+  sudo mount -t configfs none /config
+
+This will create a directory tree that looks something like this::
+
+  - /config/vkms/
+    - connectors/ -- a list of all the planes available in the VKMS driver
+      - N/ -- the connector with ID=N
+    - crtc/ -- a list of all the crtcs available in the VKMS driver
+      - N/ -- the crtc with ID=N
+    - encoders/ -- a list of all the encoders available in the VKMS driver
+      - N/ -- the encoder with ID=N
+    - planes/ -- a list of all the planes available in the VKMS driver
+      - N/ -- the plane with ID=N.
+
+Settings for each object will appear in the ``/config/vkms/<type>/<N>/`` directory.
+
 Testing With IGT
 ================
 
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index f1422bee3dcc..5c90c82fab6d 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -307,6 +307,7 @@ config DRM_VKMS
 	depends on DRM && MMU
 	select DRM_KMS_HELPER
 	select DRM_GEM_SHMEM_HELPER
+	select CONFIGFS_FS
 	select CRC32
 	default n
 	help
diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile
index 72f779cbfedd..3efb7b0f5319 100644
--- a/drivers/gpu/drm/vkms/Makefile
+++ b/drivers/gpu/drm/vkms/Makefile
@@ -3,6 +3,7 @@ vkms-y := \
 	vkms_drv.o \
 	vkms_plane.o \
 	vkms_output.o \
+	vkms_configfs.o \
 	vkms_crtc.o \
 	vkms_composer.o \
 	vkms_writeback.o
diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
new file mode 100644
index 000000000000..edaa041a830c
--- /dev/null
+++ b/drivers/gpu/drm/vkms/vkms_configfs.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <linux/configfs.h>
+#include <linux/export.h>
+#include <linux/mutex.h>
+
+#include "vkms_drv.h"
+
+static void setup_configfs_object(uint32_t id, struct config_group *object,
+				  struct config_group *parent,
+				  struct config_item_type *type)
+{
+	char name[CONFIGFS_ITEM_NAME_LEN];
+
+	snprintf(name, CONFIGFS_ITEM_NAME_LEN, "%d", id);
+	config_group_init_type_name(object, name, type);
+	configfs_add_default_group(object, parent);
+}
+
+/* connector item, e.g. /config/vkms/connectors/ID */
+
+static struct config_item_type connector_type = {
+	.ct_owner = THIS_MODULE,
+};
+
+/*  crtc item, e.g. /config/vkms/crtc/ID */
+
+static struct config_item_type crtc_type = {
+	.ct_owner = THIS_MODULE,
+};
+
+/*  encoder item, e.g. /config/vkms/encoder/ID */
+
+static struct config_item_type encoder_type = {
+	.ct_owner = THIS_MODULE,
+};
+
+void vkms_init_output_configfs(struct vkms_device *vkmsdev,
+				   struct vkms_output *output)
+{
+	setup_configfs_object(output->connector.base.id,
+				  &output->connector_config_group,
+				  &vkmsdev->configfs.connectors_group,
+				  &connector_type);
+
+	setup_configfs_object(output->crtc.base.id, &output->crtc_config_group,
+				  &vkmsdev->configfs.crtcs_group, &crtc_type);
+
+	setup_configfs_object(output->encoder.base.id,
+				  &output->encoder_config_group,
+				  &vkmsdev->configfs.encoders_group, &encoder_type);
+}
+
+/* Plane item, e.g. /config/vkms/planes/ID */
+
+static struct config_item_type plane_type = {
+	.ct_owner = THIS_MODULE,
+};
+
+void vkms_init_plane_configfs(struct vkms_device *vkmsdev,
+				  struct vkms_plane *plane)
+{
+	setup_configfs_object(plane->base.base.id, &plane->config_group,
+				  &vkmsdev->configfs.planes_group, &plane_type);
+}
+
+/* Directory groups, e.g. /config/vkms/planes */
+
+static struct config_item_type connectors_group_type = {
+	.ct_owner = THIS_MODULE,
+};
+
+static struct config_item_type crtcs_group_type = {
+	.ct_owner = THIS_MODULE,
+};
+
+static struct config_item_type encoders_group_type = {
+	.ct_owner = THIS_MODULE,
+};
+
+static struct config_item_type planes_group_type = {
+	.ct_owner = THIS_MODULE,
+};
+
+/* Root directory group, e.g. /config/vkms/ */
+
+static struct config_item_type vkms_type = {
+	.ct_owner = THIS_MODULE,
+};
+
+static struct configfs_subsystem vkms_subsys = {
+	.su_group = {
+		.cg_item = {
+			.ci_name = "vkms",
+			.ci_type = &vkms_type,
+		},
+	},
+};
+
+void vkms_init_configfs(struct vkms_device *vkmsdev)
+{
+	config_group_init(&vkms_subsys.su_group);
+	mutex_init(&vkms_subsys.su_mutex);
+
+	config_group_init_type_name(&vkmsdev->configfs.connectors_group,
+					"connectors", &connectors_group_type);
+	configfs_add_default_group(&vkmsdev->configfs.connectors_group,
+				   &vkms_subsys.su_group);
+
+	config_group_init_type_name(&vkmsdev->configfs.crtcs_group, "crtcs",
+					&crtcs_group_type);
+	configfs_add_default_group(&vkmsdev->configfs.crtcs_group,
+				   &vkms_subsys.su_group);
+
+	config_group_init_type_name(&vkmsdev->configfs.encoders_group,
+					"encoders", &encoders_group_type);
+	configfs_add_default_group(&vkmsdev->configfs.encoders_group,
+				   &vkms_subsys.su_group);
+
+	config_group_init_type_name(&vkmsdev->configfs.planes_group, "planes",
+					&planes_group_type);
+	configfs_add_default_group(&vkmsdev->configfs.planes_group,
+				   &vkms_subsys.su_group);
+}
+
+int vkms_register_configfs(void)
+{
+	return configfs_register_subsystem(&vkms_subsys);
+}
diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
index 0ffe5f0e33f7..92ca8cf2d104 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.c
+++ b/drivers/gpu/drm/vkms/vkms_drv.c
@@ -9,6 +9,7 @@
  * the GPU in DRM API tests.
  */
 
+#include <linux/configfs.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
@@ -191,6 +192,8 @@ static int vkms_create(struct vkms_config *config)
 		goto out_devres;
 	}
 
+	vkms_init_configfs(vkms_device);
+
 	ret = drm_vblank_init(&vkms_device->drm, 1);
 	if (ret) {
 		DRM_ERROR("Failed to vblank\n");
@@ -207,8 +210,15 @@ static int vkms_create(struct vkms_config *config)
 
 	drm_fbdev_generic_setup(&vkms_device->drm, 0);
 
+	ret = vkms_register_configfs();
+	if (ret)
+		goto out_drmres;
+
+
 	return 0;
 
+out_drmres:
+	drm_dev_unregister(&vkms_device->drm);
 out_devres:
 	devres_release_group(&pdev->dev, NULL);
 out_unregister:
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index 91e63b12f60f..873b91f63309 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -3,6 +3,7 @@
 #ifndef _VKMS_DRV_H_
 #define _VKMS_DRV_H_
 
+#include <linux/configfs.h>
 #include <linux/hrtimer.h>
 
 #include <drm/drm.h>
@@ -48,6 +49,7 @@ struct vkms_plane_state {
 
 struct vkms_plane {
 	struct drm_plane base;
+	struct config_group config_group;
 };
 
 /**
@@ -86,6 +88,10 @@ struct vkms_output {
 	/* protects concurrent access to composer */
 	spinlock_t lock;
 
+	struct config_group crtc_config_group;
+	struct config_group encoder_config_group;
+	struct config_group connector_config_group;
+
 	/* protected by @lock */
 	bool composer_enabled;
 	struct vkms_crtc_state *composer_state;
@@ -103,10 +109,22 @@ struct vkms_config {
 	struct vkms_device *dev;
 };
 
+struct vkms_configfs {
+	/* Directory group containing connector configs, e.g. /config/vkms/connectors/ */
+	struct config_group connectors_group;
+	/* Directory group containing CRTC configs, e.g. /config/vkms/crtcs/ */
+	struct config_group crtcs_group;
+	/* Directory group containing encoder configs, e.g. /config/vkms/encoders/ */
+	struct config_group encoders_group;
+	/* Directory group containing plane configs, e.g. /config/vkms/planes/ */
+	struct config_group planes_group;
+};
+
 struct vkms_device {
 	struct drm_device drm;
 	struct platform_device *platform;
 	struct vkms_output output;
+	struct vkms_configfs configfs;
 	const struct vkms_config *config;
 };
 
@@ -145,4 +163,11 @@ void vkms_set_composer(struct vkms_output *out, bool enabled);
 /* Writeback */
 int vkms_enable_writeback_connector(struct vkms_device *vkmsdev);
 
+/* ConfigFS Support */
+void vkms_init_configfs(struct vkms_device *vkmsdev);
+int vkms_register_configfs(void);
+
+void vkms_init_plane_configfs(struct vkms_device *vkmsdev, struct  vkms_plane *plane);
+void vkms_init_output_configfs(struct vkms_device *vkmsdev, struct vkms_output *output);
+
 #endif /* _VKMS_DRV_H_ */
diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c
index ba0e82ae549a..fa80d27118c8 100644
--- a/drivers/gpu/drm/vkms/vkms_output.c
+++ b/drivers/gpu/drm/vkms/vkms_output.c
@@ -111,6 +111,8 @@ int vkms_output_init(struct vkms_device *vkmsdev, int index)
 
 	drm_mode_config_reset(dev);
 
+	vkms_init_output_configfs(vkmsdev, output);
+
 	return 0;
 
 err_attach:
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
index d8eb674b49a6..4b93cfa1bb19 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -195,5 +195,7 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
 
 	drm_plane_helper_add(&plane->base, funcs);
 
+	vkms_init_plane_configfs(vkmsdev, plane);
+
 	return plane;
 }
