cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vkms_plane.c (5374B)


      1// SPDX-License-Identifier: GPL-2.0+
      2
      3#include <linux/iosys-map.h>
      4
      5#include <drm/drm_atomic.h>
      6#include <drm/drm_atomic_helper.h>
      7#include <drm/drm_fourcc.h>
      8#include <drm/drm_gem_atomic_helper.h>
      9#include <drm/drm_gem_framebuffer_helper.h>
     10#include <drm/drm_plane_helper.h>
     11
     12#include "vkms_drv.h"
     13
     14static const u32 vkms_formats[] = {
     15	DRM_FORMAT_XRGB8888,
     16};
     17
     18static const u32 vkms_plane_formats[] = {
     19	DRM_FORMAT_ARGB8888,
     20	DRM_FORMAT_XRGB8888
     21};
     22
     23static struct drm_plane_state *
     24vkms_plane_duplicate_state(struct drm_plane *plane)
     25{
     26	struct vkms_plane_state *vkms_state;
     27	struct vkms_composer *composer;
     28
     29	vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL);
     30	if (!vkms_state)
     31		return NULL;
     32
     33	composer = kzalloc(sizeof(*composer), GFP_KERNEL);
     34	if (!composer) {
     35		DRM_DEBUG_KMS("Couldn't allocate composer\n");
     36		kfree(vkms_state);
     37		return NULL;
     38	}
     39
     40	vkms_state->composer = composer;
     41
     42	__drm_gem_duplicate_shadow_plane_state(plane, &vkms_state->base);
     43
     44	return &vkms_state->base.base;
     45}
     46
     47static void vkms_plane_destroy_state(struct drm_plane *plane,
     48				     struct drm_plane_state *old_state)
     49{
     50	struct vkms_plane_state *vkms_state = to_vkms_plane_state(old_state);
     51	struct drm_crtc *crtc = vkms_state->base.base.crtc;
     52
     53	if (crtc) {
     54		/* dropping the reference we acquired in
     55		 * vkms_primary_plane_update()
     56		 */
     57		if (drm_framebuffer_read_refcount(&vkms_state->composer->fb))
     58			drm_framebuffer_put(&vkms_state->composer->fb);
     59	}
     60
     61	kfree(vkms_state->composer);
     62	vkms_state->composer = NULL;
     63
     64	__drm_gem_destroy_shadow_plane_state(&vkms_state->base);
     65	kfree(vkms_state);
     66}
     67
     68static void vkms_plane_reset(struct drm_plane *plane)
     69{
     70	struct vkms_plane_state *vkms_state;
     71
     72	if (plane->state) {
     73		vkms_plane_destroy_state(plane, plane->state);
     74		plane->state = NULL; /* must be set to NULL here */
     75	}
     76
     77	vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL);
     78	if (!vkms_state) {
     79		DRM_ERROR("Cannot allocate vkms_plane_state\n");
     80		return;
     81	}
     82
     83	__drm_gem_reset_shadow_plane(plane, &vkms_state->base);
     84}
     85
     86static const struct drm_plane_funcs vkms_plane_funcs = {
     87	.update_plane		= drm_atomic_helper_update_plane,
     88	.disable_plane		= drm_atomic_helper_disable_plane,
     89	.reset			= vkms_plane_reset,
     90	.atomic_duplicate_state = vkms_plane_duplicate_state,
     91	.atomic_destroy_state	= vkms_plane_destroy_state,
     92};
     93
     94static void vkms_plane_atomic_update(struct drm_plane *plane,
     95				     struct drm_atomic_state *state)
     96{
     97	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
     98									   plane);
     99	struct vkms_plane_state *vkms_plane_state;
    100	struct drm_shadow_plane_state *shadow_plane_state;
    101	struct drm_framebuffer *fb = new_state->fb;
    102	struct vkms_composer *composer;
    103
    104	if (!new_state->crtc || !fb)
    105		return;
    106
    107	vkms_plane_state = to_vkms_plane_state(new_state);
    108	shadow_plane_state = &vkms_plane_state->base;
    109
    110	composer = vkms_plane_state->composer;
    111	memcpy(&composer->src, &new_state->src, sizeof(struct drm_rect));
    112	memcpy(&composer->dst, &new_state->dst, sizeof(struct drm_rect));
    113	memcpy(&composer->fb, fb, sizeof(struct drm_framebuffer));
    114	memcpy(&composer->map, &shadow_plane_state->data, sizeof(composer->map));
    115	drm_framebuffer_get(&composer->fb);
    116	composer->offset = fb->offsets[0];
    117	composer->pitch = fb->pitches[0];
    118	composer->cpp = fb->format->cpp[0];
    119}
    120
    121static int vkms_plane_atomic_check(struct drm_plane *plane,
    122				   struct drm_atomic_state *state)
    123{
    124	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
    125										 plane);
    126	struct drm_crtc_state *crtc_state;
    127	bool can_position = false;
    128	int ret;
    129
    130	if (!new_plane_state->fb || WARN_ON(!new_plane_state->crtc))
    131		return 0;
    132
    133	crtc_state = drm_atomic_get_crtc_state(state,
    134					       new_plane_state->crtc);
    135	if (IS_ERR(crtc_state))
    136		return PTR_ERR(crtc_state);
    137
    138	if (plane->type != DRM_PLANE_TYPE_PRIMARY)
    139		can_position = true;
    140
    141	ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
    142						  DRM_PLANE_HELPER_NO_SCALING,
    143						  DRM_PLANE_HELPER_NO_SCALING,
    144						  can_position, true);
    145	if (ret != 0)
    146		return ret;
    147
    148	/* for now primary plane must be visible and full screen */
    149	if (!new_plane_state->visible && !can_position)
    150		return -EINVAL;
    151
    152	return 0;
    153}
    154
    155static const struct drm_plane_helper_funcs vkms_primary_helper_funcs = {
    156	.atomic_update		= vkms_plane_atomic_update,
    157	.atomic_check		= vkms_plane_atomic_check,
    158	DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
    159};
    160
    161struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
    162				   enum drm_plane_type type, int index)
    163{
    164	struct drm_device *dev = &vkmsdev->drm;
    165	const struct drm_plane_helper_funcs *funcs;
    166	struct vkms_plane *plane;
    167	const u32 *formats;
    168	int nformats;
    169
    170	switch (type) {
    171	case DRM_PLANE_TYPE_PRIMARY:
    172		formats = vkms_formats;
    173		nformats = ARRAY_SIZE(vkms_formats);
    174		funcs = &vkms_primary_helper_funcs;
    175		break;
    176	case DRM_PLANE_TYPE_CURSOR:
    177	case DRM_PLANE_TYPE_OVERLAY:
    178		formats = vkms_plane_formats;
    179		nformats = ARRAY_SIZE(vkms_plane_formats);
    180		funcs = &vkms_primary_helper_funcs;
    181		break;
    182	default:
    183		formats = vkms_formats;
    184		nformats = ARRAY_SIZE(vkms_formats);
    185		funcs = &vkms_primary_helper_funcs;
    186		break;
    187	}
    188
    189	plane = drmm_universal_plane_alloc(dev, struct vkms_plane, base, 1 << index,
    190					   &vkms_plane_funcs,
    191					   formats, nformats,
    192					   NULL, type, NULL);
    193	if (IS_ERR(plane))
    194		return plane;
    195
    196	drm_plane_helper_add(&plane->base, funcs);
    197
    198	return plane;
    199}