[PATCH v2 1/4] drm/msm: share a page of kernel state with the GPU
From: Dmitry Baryshkov
Date: Sat Oct 31 2026 - 12:12:38 EST
Some state the kernel keeps has to be applied to values the GPU produces
by itself, the first case being the always-on counter that restarts
across a GPU power collapse. A GET_PARAM can't carry it, as command
streams need the value at the time they execute.
Allocate one page in the global GPU address space, read-only to the GPU
and not privileged, so the command streams of every context can read
it, and report its address. Start it with a flags word so that fields
appended later can be announced.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxxxxxxxx>
---
drivers/gpu/drm/msm/adreno/adreno_gpu.c | 3 +++
drivers/gpu/drm/msm/msm_gpu.c | 15 +++++++++++++++
drivers/gpu/drm/msm/msm_gpu.h | 5 +++++
include/uapi/drm/msm_drm.h | 9 +++++++++
4 files changed, 32 insertions(+)
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index dadfe4c69438..0adf56fb9563 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -404,6 +404,9 @@ int adreno_get_param(struct msm_gpu *gpu, struct msm_context *ctx,
return 0;
}
return -EINVAL;
+ case MSM_PARAM_VDSO_IOVA:
+ *value = gpu->vdso_iova;
+ return 0;
case MSM_PARAM_PRIORITIES:
*value = gpu->nr_rings * NR_SCHED_PRIORITIES;
return 0;
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 0c2c35636251..747cd90e329a 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -989,6 +989,19 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
msm_gem_object_set_name(gpu->memptrs_bo, "memptrs");
+ gpu->vdso = msm_gem_kernel_new(drm, PAGE_SIZE,
+ MSM_BO_WC | MSM_BO_GPU_READONLY, gpu->vm, &gpu->vdso_bo,
+ &gpu->vdso_iova);
+
+ if (IS_ERR(gpu->vdso)) {
+ ret = PTR_ERR(gpu->vdso);
+ gpu->vdso = NULL;
+ DRM_DEV_ERROR(drm->dev, "could not allocate vdso: %d\n", ret);
+ goto fail;
+ }
+
+ msm_gem_object_set_name(gpu->vdso_bo, "vdso");
+
if (nr_rings > ARRAY_SIZE(gpu->rb)) {
DRM_DEV_INFO_ONCE(drm->dev, "Only creating %zu ringbuffers\n",
ARRAY_SIZE(gpu->rb));
@@ -1033,6 +1046,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
gpu->rb[i] = NULL;
}
+ msm_gem_kernel_put(gpu->vdso_bo, gpu->vm);
msm_gem_kernel_put(gpu->memptrs_bo, gpu->vm);
platform_set_drvdata(pdev, NULL);
@@ -1050,6 +1064,7 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)
gpu->rb[i] = NULL;
}
+ msm_gem_kernel_put(gpu->vdso_bo, gpu->vm);
msm_gem_kernel_put(gpu->memptrs_bo, gpu->vm);
if (!IS_ERR_OR_NULL(gpu->vm)) {
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index d27d54bdb7a7..f78f3bc62977 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -252,6 +252,11 @@ struct msm_gpu {
struct drm_gem_object *memptrs_bo;
+ /* page of kernel state shared read-only with the GPU: */
+ struct drm_gem_object *vdso_bo;
+ struct drm_msm_vdso *vdso;
+ uint64_t vdso_iova;
+
struct msm_gpu_devfreq devfreq;
uint32_t suspend_count;
diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h
index 3d363f12f66a..f8bf48fdc339 100644
--- a/include/uapi/drm/msm_drm.h
+++ b/include/uapi/drm/msm_drm.h
@@ -118,6 +118,7 @@ struct drm_msm_timespec {
*/
#define MSM_PARAM_EN_VM_BIND 0x16 /* WO, once */
#define MSM_PARAM_AQE 0x17 /* RO */
+#define MSM_PARAM_VDSO_IOVA 0x18 /* RO: GPU address of struct drm_msm_vdso */
/* For backwards compat. The original support for preemption was based on
* a single ring per priority level so # of priority levels equals the #
@@ -127,6 +128,14 @@ struct drm_msm_timespec {
*/
#define MSM_PARAM_NR_RINGS MSM_PARAM_PRIORITIES
+/* A page of kernel state that the GPU can read, at MSM_PARAM_VDSO_IOVA, for
+ * command streams to use. New fields are only ever appended, and the kernel
+ * sets a bit in @flags for each one that needs announcing.
+ */
+struct drm_msm_vdso {
+ __u64 flags;
+};
+
struct drm_msm_param {
__u32 pipe; /* in, MSM_PIPE_x */
__u32 param; /* in, MSM_PARAM_x */
--
2.47.3