Loading drivers/gpu/drm/msm/sde/sde_crtc.c +38 −30 Original line number Original line Diff line number Diff line Loading @@ -4329,13 +4329,14 @@ static int _sde_crtc_excl_dim_layer_check(struct drm_crtc_state *state, } } static int _sde_crtc_check_secure_state(struct drm_crtc *crtc, static int _sde_crtc_check_secure_state(struct drm_crtc *crtc, struct drm_crtc_state *state) struct drm_crtc_state *state, struct plane_state pstates[], int cnt) { { struct drm_encoder *encoder; struct drm_encoder *encoder; struct sde_crtc_state *cstate; struct sde_crtc_state *cstate; uint32_t secure; uint32_t secure; uint32_t fb_ns = 0, fb_sec = 0, fb_sec_dir = 0; uint32_t fb_ns = 0, fb_sec = 0, fb_sec_dir = 0; int encoder_cnt = 0; int encoder_cnt = 0, i; int rc; int rc; if (!crtc || !state) { if (!crtc || !state) { Loading @@ -4345,31 +4346,40 @@ static int _sde_crtc_check_secure_state(struct drm_crtc *crtc, cstate = to_sde_crtc_state(state); cstate = to_sde_crtc_state(state); secure = sde_crtc_get_property(cstate, secure = sde_crtc_get_property(cstate, CRTC_PROP_SECURITY_LEVEL); CRTC_PROP_SECURITY_LEVEL); rc = _sde_crtc_find_plane_fb_modes(state, rc = _sde_crtc_find_plane_fb_modes(state, &fb_ns, &fb_sec, &fb_sec_dir); &fb_ns, &fb_sec, &fb_sec_dir); if (rc) if (rc) return rc; return rc; /** if (secure == SDE_DRM_SEC_ONLY) { * validate planes /* * fb_sec_dir is for secure camera preview and secure display use case, * validate planes - only fb_sec_dir is allowed during sec_crtc * fb_sec is for secure video playback, * - fb_sec_dir is for secure camera preview and * fb_ns is for normal non secure use cases. * secure display use case * - fb_sec is for secure video playback * - fb_ns is for normal non secure use cases */ */ if ((secure == SDE_DRM_SEC_ONLY) && if (fb_ns || fb_sec) { (fb_ns || fb_sec || (fb_sec && fb_sec_dir))) { SDE_ERROR( SDE_ERROR( "crtc%d: invalid planes fb_modes Sec:%d, NS:%d, Sec_Dir:%d\n", "crtc%d: invalid fb_modes Sec:%d, NS:%d, Sec_Dir:%d\n", crtc->base.id, fb_sec, fb_ns, fb_sec_dir); crtc->base.id, fb_sec, fb_ns, fb_sec_dir); return -EINVAL; return -EINVAL; } } /** /* only one blending stage is allowed in sec_crtc */ for (i = 1; i < cnt; i++) { if (pstates[i].stage != pstates[i-1].stage) { SDE_ERROR( "crtc%d: invalid blend stages %d:%d, %d:%d\n", crtc->base.id, i, pstates[i].stage, i-1, pstates[i-1].stage); return -EINVAL; } } } /* * secure_crtc is not allowed in a shared toppolgy * secure_crtc is not allowed in a shared toppolgy * across different encoders. * across different encoders. */ */ Loading @@ -4378,17 +4388,15 @@ static int _sde_crtc_check_secure_state(struct drm_crtc *crtc, if (encoder->crtc == crtc) if (encoder->crtc == crtc) encoder_cnt++; encoder_cnt++; if (encoder_cnt > if (encoder_cnt > MAX_ALLOWED_ENCODER_CNT_PER_SECURE_CRTC) { MAX_ALLOWED_ENCODER_CNT_PER_SECURE_CRTC) { SDE_ERROR("crtc%d, invalid virtual encoder crtc%d\n", SDE_ERROR( crtc->base.id, encoder_cnt); "crtc%d, invalid virtual encoder crtc%d\n", crtc->base.id, encoder_cnt); return -EINVAL; return -EINVAL; } } } } SDE_DEBUG("crtc:%d Secure validation successful\n", crtc->base.id); SDE_DEBUG("crtc:%d Secure validation successful\n", crtc->base.id); return 0; return 0; } } Loading Loading @@ -4445,10 +4453,6 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, _sde_crtc_setup_is_ppsplit(state); _sde_crtc_setup_is_ppsplit(state); _sde_crtc_setup_lm_bounds(crtc, state); _sde_crtc_setup_lm_bounds(crtc, state); rc = _sde_crtc_check_secure_state(crtc, state); if (rc) return rc; /* get plane state for all drm planes associated with crtc state */ /* get plane state for all drm planes associated with crtc state */ drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) { drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) { if (IS_ERR_OR_NULL(pstate)) { if (IS_ERR_OR_NULL(pstate)) { Loading Loading @@ -4522,6 +4526,10 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, /* assign mixer stages based on sorted zpos property */ /* assign mixer stages based on sorted zpos property */ sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL); sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL); rc = _sde_crtc_check_secure_state(crtc, state, pstates, cnt); if (rc) goto end; rc = _sde_crtc_excl_dim_layer_check(state, pstates, cnt); rc = _sde_crtc_excl_dim_layer_check(state, pstates, cnt); if (rc) if (rc) goto end; goto end; Loading drivers/gpu/drm/msm/sde/sde_kms.c +44 −36 Original line number Original line Diff line number Diff line Loading @@ -1910,10 +1910,10 @@ static int sde_kms_check_secure_transition(struct msm_kms *kms, struct sde_kms *sde_kms; struct sde_kms *sde_kms; struct drm_device *dev; struct drm_device *dev; struct drm_crtc *crtc; struct drm_crtc *crtc; struct drm_crtc *sec_crtc = NULL, *temp_crtc = NULL; struct drm_crtc *cur_crtc = NULL, *global_crtc = NULL; struct drm_crtc_state *crtc_state; struct drm_crtc_state *crtc_state; int secure_crtc_cnt = 0, active_crtc_cnt = 0; int active_crtc_cnt = 0, global_active_crtc_cnt = 0; int secure_global_crtc_cnt = 0, active_mode_crtc_cnt = 0; bool sec_session = false, global_sec_session = false; int i; int i; if (!kms || !state) { if (!kms || !state) { Loading @@ -1921,56 +1921,64 @@ static int sde_kms_check_secure_transition(struct msm_kms *kms, SDE_ERROR("invalid arguments\n"); SDE_ERROR("invalid arguments\n"); } } /* iterate state object for active and secure crtc */ sde_kms = to_sde_kms(kms); dev = sde_kms->dev; /* iterate state object for active secure/non-secure crtc */ for_each_crtc_in_state(state, crtc, crtc_state, i) { for_each_crtc_in_state(state, crtc, crtc_state, i) { if (!crtc_state->active) if (!crtc_state->active) continue; continue; active_crtc_cnt++; active_crtc_cnt++; if (sde_crtc_get_secure_level(crtc, crtc_state) == if (sde_crtc_get_secure_level(crtc, crtc_state) == SDE_DRM_SEC_ONLY) { SDE_DRM_SEC_ONLY) sec_crtc = crtc; sec_session = true; secure_crtc_cnt++; } } /* bail out from further validation if no secure ctrc */ if (!secure_crtc_cnt) return 0; if ((secure_crtc_cnt > MAX_ALLOWED_SECURE_CLIENT_CNT) || cur_crtc = crtc; (secure_crtc_cnt && (active_crtc_cnt > MAX_ALLOWED_CRTC_CNT_DURING_SECURE))) { SDE_ERROR("Secure check failed active:%d, secure:%d\n", active_crtc_cnt, secure_crtc_cnt); return -EPERM; } } sde_kms = to_sde_kms(kms); dev = sde_kms->dev; /* iterate global list for active and secure crtc */ /* iterate global list for active and secure crtc */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (!crtc->state->active) if (!crtc->state->active) continue; continue; active_mode_crtc_cnt++; global_active_crtc_cnt++; if (sde_crtc_get_secure_level(crtc, crtc->state) == if (sde_crtc_get_secure_level(crtc, crtc->state) == SDE_DRM_SEC_ONLY) { SDE_DRM_SEC_ONLY) secure_global_crtc_cnt++; global_sec_session = true; temp_crtc = crtc; } global_crtc = crtc; } } /** /* * if more than one crtc is active fail * - fail secure crtc commit, if any other crtc session is already * check if the previous and current commit secure * in progress * are same * - fail non-secure crtc commit, if any secure crtc session is already * in progress */ */ if (secure_crtc_cnt && ((active_mode_crtc_cnt > 1) || if (global_sec_session || sec_session) { (secure_global_crtc_cnt && (temp_crtc != sec_crtc)))) if ((global_active_crtc_cnt > SDE_ERROR("Secure check failed active:%d crtc_id:%d\n", MAX_ALLOWED_CRTC_CNT_DURING_SECURE) || active_mode_crtc_cnt, temp_crtc->base.id); (active_crtc_cnt > MAX_ALLOWED_CRTC_CNT_DURING_SECURE)) { SDE_ERROR( "Secure check failed global_active:%d active:%d\n", global_active_crtc_cnt, active_crtc_cnt); return -EPERM; /* * As only one crtc is allowed during secure session, the crtc * in this commit should match with the global crtc, if it * exists */ } else if (global_crtc && (global_crtc != cur_crtc)) { SDE_ERROR( "crtc%d-sec%d not allowed during crtc%d-sec%d\n", cur_crtc->base.id, sec_session, global_crtc->base.id, global_sec_session); return -EPERM; } } return 0; return 0; } } Loading Loading
drivers/gpu/drm/msm/sde/sde_crtc.c +38 −30 Original line number Original line Diff line number Diff line Loading @@ -4329,13 +4329,14 @@ static int _sde_crtc_excl_dim_layer_check(struct drm_crtc_state *state, } } static int _sde_crtc_check_secure_state(struct drm_crtc *crtc, static int _sde_crtc_check_secure_state(struct drm_crtc *crtc, struct drm_crtc_state *state) struct drm_crtc_state *state, struct plane_state pstates[], int cnt) { { struct drm_encoder *encoder; struct drm_encoder *encoder; struct sde_crtc_state *cstate; struct sde_crtc_state *cstate; uint32_t secure; uint32_t secure; uint32_t fb_ns = 0, fb_sec = 0, fb_sec_dir = 0; uint32_t fb_ns = 0, fb_sec = 0, fb_sec_dir = 0; int encoder_cnt = 0; int encoder_cnt = 0, i; int rc; int rc; if (!crtc || !state) { if (!crtc || !state) { Loading @@ -4345,31 +4346,40 @@ static int _sde_crtc_check_secure_state(struct drm_crtc *crtc, cstate = to_sde_crtc_state(state); cstate = to_sde_crtc_state(state); secure = sde_crtc_get_property(cstate, secure = sde_crtc_get_property(cstate, CRTC_PROP_SECURITY_LEVEL); CRTC_PROP_SECURITY_LEVEL); rc = _sde_crtc_find_plane_fb_modes(state, rc = _sde_crtc_find_plane_fb_modes(state, &fb_ns, &fb_sec, &fb_sec_dir); &fb_ns, &fb_sec, &fb_sec_dir); if (rc) if (rc) return rc; return rc; /** if (secure == SDE_DRM_SEC_ONLY) { * validate planes /* * fb_sec_dir is for secure camera preview and secure display use case, * validate planes - only fb_sec_dir is allowed during sec_crtc * fb_sec is for secure video playback, * - fb_sec_dir is for secure camera preview and * fb_ns is for normal non secure use cases. * secure display use case * - fb_sec is for secure video playback * - fb_ns is for normal non secure use cases */ */ if ((secure == SDE_DRM_SEC_ONLY) && if (fb_ns || fb_sec) { (fb_ns || fb_sec || (fb_sec && fb_sec_dir))) { SDE_ERROR( SDE_ERROR( "crtc%d: invalid planes fb_modes Sec:%d, NS:%d, Sec_Dir:%d\n", "crtc%d: invalid fb_modes Sec:%d, NS:%d, Sec_Dir:%d\n", crtc->base.id, fb_sec, fb_ns, fb_sec_dir); crtc->base.id, fb_sec, fb_ns, fb_sec_dir); return -EINVAL; return -EINVAL; } } /** /* only one blending stage is allowed in sec_crtc */ for (i = 1; i < cnt; i++) { if (pstates[i].stage != pstates[i-1].stage) { SDE_ERROR( "crtc%d: invalid blend stages %d:%d, %d:%d\n", crtc->base.id, i, pstates[i].stage, i-1, pstates[i-1].stage); return -EINVAL; } } } /* * secure_crtc is not allowed in a shared toppolgy * secure_crtc is not allowed in a shared toppolgy * across different encoders. * across different encoders. */ */ Loading @@ -4378,17 +4388,15 @@ static int _sde_crtc_check_secure_state(struct drm_crtc *crtc, if (encoder->crtc == crtc) if (encoder->crtc == crtc) encoder_cnt++; encoder_cnt++; if (encoder_cnt > if (encoder_cnt > MAX_ALLOWED_ENCODER_CNT_PER_SECURE_CRTC) { MAX_ALLOWED_ENCODER_CNT_PER_SECURE_CRTC) { SDE_ERROR("crtc%d, invalid virtual encoder crtc%d\n", SDE_ERROR( crtc->base.id, encoder_cnt); "crtc%d, invalid virtual encoder crtc%d\n", crtc->base.id, encoder_cnt); return -EINVAL; return -EINVAL; } } } } SDE_DEBUG("crtc:%d Secure validation successful\n", crtc->base.id); SDE_DEBUG("crtc:%d Secure validation successful\n", crtc->base.id); return 0; return 0; } } Loading Loading @@ -4445,10 +4453,6 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, _sde_crtc_setup_is_ppsplit(state); _sde_crtc_setup_is_ppsplit(state); _sde_crtc_setup_lm_bounds(crtc, state); _sde_crtc_setup_lm_bounds(crtc, state); rc = _sde_crtc_check_secure_state(crtc, state); if (rc) return rc; /* get plane state for all drm planes associated with crtc state */ /* get plane state for all drm planes associated with crtc state */ drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) { drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) { if (IS_ERR_OR_NULL(pstate)) { if (IS_ERR_OR_NULL(pstate)) { Loading Loading @@ -4522,6 +4526,10 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, /* assign mixer stages based on sorted zpos property */ /* assign mixer stages based on sorted zpos property */ sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL); sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL); rc = _sde_crtc_check_secure_state(crtc, state, pstates, cnt); if (rc) goto end; rc = _sde_crtc_excl_dim_layer_check(state, pstates, cnt); rc = _sde_crtc_excl_dim_layer_check(state, pstates, cnt); if (rc) if (rc) goto end; goto end; Loading
drivers/gpu/drm/msm/sde/sde_kms.c +44 −36 Original line number Original line Diff line number Diff line Loading @@ -1910,10 +1910,10 @@ static int sde_kms_check_secure_transition(struct msm_kms *kms, struct sde_kms *sde_kms; struct sde_kms *sde_kms; struct drm_device *dev; struct drm_device *dev; struct drm_crtc *crtc; struct drm_crtc *crtc; struct drm_crtc *sec_crtc = NULL, *temp_crtc = NULL; struct drm_crtc *cur_crtc = NULL, *global_crtc = NULL; struct drm_crtc_state *crtc_state; struct drm_crtc_state *crtc_state; int secure_crtc_cnt = 0, active_crtc_cnt = 0; int active_crtc_cnt = 0, global_active_crtc_cnt = 0; int secure_global_crtc_cnt = 0, active_mode_crtc_cnt = 0; bool sec_session = false, global_sec_session = false; int i; int i; if (!kms || !state) { if (!kms || !state) { Loading @@ -1921,56 +1921,64 @@ static int sde_kms_check_secure_transition(struct msm_kms *kms, SDE_ERROR("invalid arguments\n"); SDE_ERROR("invalid arguments\n"); } } /* iterate state object for active and secure crtc */ sde_kms = to_sde_kms(kms); dev = sde_kms->dev; /* iterate state object for active secure/non-secure crtc */ for_each_crtc_in_state(state, crtc, crtc_state, i) { for_each_crtc_in_state(state, crtc, crtc_state, i) { if (!crtc_state->active) if (!crtc_state->active) continue; continue; active_crtc_cnt++; active_crtc_cnt++; if (sde_crtc_get_secure_level(crtc, crtc_state) == if (sde_crtc_get_secure_level(crtc, crtc_state) == SDE_DRM_SEC_ONLY) { SDE_DRM_SEC_ONLY) sec_crtc = crtc; sec_session = true; secure_crtc_cnt++; } } /* bail out from further validation if no secure ctrc */ if (!secure_crtc_cnt) return 0; if ((secure_crtc_cnt > MAX_ALLOWED_SECURE_CLIENT_CNT) || cur_crtc = crtc; (secure_crtc_cnt && (active_crtc_cnt > MAX_ALLOWED_CRTC_CNT_DURING_SECURE))) { SDE_ERROR("Secure check failed active:%d, secure:%d\n", active_crtc_cnt, secure_crtc_cnt); return -EPERM; } } sde_kms = to_sde_kms(kms); dev = sde_kms->dev; /* iterate global list for active and secure crtc */ /* iterate global list for active and secure crtc */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (!crtc->state->active) if (!crtc->state->active) continue; continue; active_mode_crtc_cnt++; global_active_crtc_cnt++; if (sde_crtc_get_secure_level(crtc, crtc->state) == if (sde_crtc_get_secure_level(crtc, crtc->state) == SDE_DRM_SEC_ONLY) { SDE_DRM_SEC_ONLY) secure_global_crtc_cnt++; global_sec_session = true; temp_crtc = crtc; } global_crtc = crtc; } } /** /* * if more than one crtc is active fail * - fail secure crtc commit, if any other crtc session is already * check if the previous and current commit secure * in progress * are same * - fail non-secure crtc commit, if any secure crtc session is already * in progress */ */ if (secure_crtc_cnt && ((active_mode_crtc_cnt > 1) || if (global_sec_session || sec_session) { (secure_global_crtc_cnt && (temp_crtc != sec_crtc)))) if ((global_active_crtc_cnt > SDE_ERROR("Secure check failed active:%d crtc_id:%d\n", MAX_ALLOWED_CRTC_CNT_DURING_SECURE) || active_mode_crtc_cnt, temp_crtc->base.id); (active_crtc_cnt > MAX_ALLOWED_CRTC_CNT_DURING_SECURE)) { SDE_ERROR( "Secure check failed global_active:%d active:%d\n", global_active_crtc_cnt, active_crtc_cnt); return -EPERM; /* * As only one crtc is allowed during secure session, the crtc * in this commit should match with the global crtc, if it * exists */ } else if (global_crtc && (global_crtc != cur_crtc)) { SDE_ERROR( "crtc%d-sec%d not allowed during crtc%d-sec%d\n", cur_crtc->base.id, sec_session, global_crtc->base.id, global_sec_session); return -EPERM; } } return 0; return 0; } } Loading