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 <[email protected]> --- 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
