Skip to content

Commit 4060836

Browse files
authored
Merge pull request #243 from mukeshojha-linux/6.18.y
6.18.y : Update remoteproc KVM support to the latest patches merged upstream
2 parents 93be04f + 73e52bd commit 4060836

4 files changed

Lines changed: 140 additions & 141 deletions

File tree

drivers/firmware/qcom/qcom_scm.c

Lines changed: 114 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,7 @@ enum qcom_scm_qseecom_tz_cmd_info {
112112
QSEECOM_TZ_CMD_INFO_VERSION = 3,
113113
};
114114

115-
enum qcom_scm_rsctable_resp_type {
116-
RSCTABLE_BUFFER_NOT_SUFFICIENT = 20,
117-
};
115+
#define RSCTABLE_BUFFER_NOT_SUFFICIENT 20
118116

119117
#define QSEECOM_MAX_APP_NAME_SIZE 64
120118
#define SHMBRIDGE_RESULT_NOTSUPP 4
@@ -564,8 +562,8 @@ static void qcom_scm_set_download_mode(u32 dload_mode)
564562
}
565563

566564
/**
567-
* devm_qcom_scm_pas_context_init() - Initialize peripheral authentication service
568-
* context for a given peripheral
565+
* devm_qcom_scm_pas_context_alloc() - Allocate peripheral authentication service
566+
* context for a given peripheral
569567
*
570568
* PAS context is device-resource managed, so the caller does not need
571569
* to worry about freeing the context memory.
@@ -575,12 +573,12 @@ static void qcom_scm_set_download_mode(u32 dload_mode)
575573
* @mem_phys: Subsystem reserve memory start address
576574
* @mem_size: Subsystem reserve memory size
577575
*
578-
* Upon successful, returns the PAS context or ERR_PTR() of the error otherwise.
576+
* Returns: The new PAS context, or ERR_PTR() on failure.
579577
*/
580-
struct qcom_scm_pas_context *devm_qcom_scm_pas_context_init(struct device *dev,
581-
u32 pas_id,
582-
phys_addr_t mem_phys,
583-
size_t mem_size)
578+
struct qcom_scm_pas_context *devm_qcom_scm_pas_context_alloc(struct device *dev,
579+
u32 pas_id,
580+
phys_addr_t mem_phys,
581+
size_t mem_size)
584582
{
585583
struct qcom_scm_pas_context *ctx;
586584

@@ -595,7 +593,7 @@ struct qcom_scm_pas_context *devm_qcom_scm_pas_context_init(struct device *dev,
595593

596594
return ctx;
597595
}
598-
EXPORT_SYMBOL_GPL(devm_qcom_scm_pas_context_init);
596+
EXPORT_SYMBOL_GPL(devm_qcom_scm_pas_context_alloc);
599597

600598
static int __qcom_scm_pas_init_image(u32 pas_id, dma_addr_t mdata_phys,
601599
struct qcom_scm_res *res)
@@ -677,7 +675,7 @@ int qcom_scm_pas_init_image(u32 pas_id, const void *metadata, size_t size,
677675
void *mdata_buf;
678676
int ret;
679677

680-
if (ctx && ctx->has_iommu)
678+
if (ctx && ctx->use_tzmem)
681679
return qcom_scm_pas_prep_and_init_image(ctx, metadata, size);
682680

683681
/*
@@ -721,7 +719,7 @@ void qcom_scm_pas_metadata_release(struct qcom_scm_pas_context *ctx)
721719
if (!ctx->ptr)
722720
return;
723721

724-
if (ctx->has_iommu)
722+
if (ctx->use_tzmem)
725723
qcom_tzmem_free(ctx->ptr);
726724
else
727725
dma_free_coherent(__scm->dev, ctx->size, ctx->ptr, ctx->phys);
@@ -771,8 +769,9 @@ int qcom_scm_pas_mem_setup(u32 pas_id, phys_addr_t addr, phys_addr_t size)
771769
}
772770
EXPORT_SYMBOL_GPL(qcom_scm_pas_mem_setup);
773771

774-
static int __qcom_scm_pas_get_rsc_table(u32 pas_id, void *input_rt, size_t input_rt_size,
775-
void **output_rt, size_t *output_rt_size)
772+
static void *__qcom_scm_pas_get_rsc_table(u32 pas_id, void *input_rt_tzm,
773+
size_t input_rt_size,
774+
size_t *output_rt_size)
776775
{
777776
struct qcom_scm_desc desc = {
778777
.svc = QCOM_SCM_SVC_PIL,
@@ -782,80 +781,44 @@ static int __qcom_scm_pas_get_rsc_table(u32 pas_id, void *input_rt, size_t input
782781
.args[0] = pas_id,
783782
.owner = ARM_SMCCC_OWNER_SIP,
784783
};
785-
void *input_rt_buf, *output_rt_buf;
786-
struct resource_table *rsc;
787784
struct qcom_scm_res res;
785+
void *output_rt_tzm;
788786
int ret;
789787

790-
ret = qcom_scm_clk_enable();
791-
if (ret)
792-
return ret;
793-
794-
ret = qcom_scm_bw_enable();
795-
if (ret)
796-
goto disable_clk;
797-
798-
/*
799-
* TrustZone can not accept buffer as NULL value as argument Hence,
800-
* we need to pass a input buffer indicating that subsystem firmware
801-
* does not have resource table by filling resource table structure.
802-
*/
803-
if (!input_rt)
804-
input_rt_size = sizeof(*rsc);
805-
806-
input_rt_buf = qcom_tzmem_alloc(__scm->mempool, input_rt_size, GFP_KERNEL);
807-
if (!input_rt_buf) {
808-
ret = -ENOMEM;
809-
goto disable_scm_bw;
810-
}
811-
812-
if (!input_rt) {
813-
rsc = input_rt_buf;
814-
rsc->num = 0;
815-
} else {
816-
memcpy(input_rt_buf, input_rt, input_rt_size);
817-
}
818-
819-
output_rt_buf = qcom_tzmem_alloc(__scm->mempool, *output_rt_size, GFP_KERNEL);
820-
if (!output_rt_buf) {
821-
ret = -ENOMEM;
822-
goto free_input_rt_buf;
823-
}
788+
output_rt_tzm = qcom_tzmem_alloc(__scm->mempool, *output_rt_size, GFP_KERNEL);
789+
if (!output_rt_tzm)
790+
return ERR_PTR(-ENOMEM);
824791

825-
desc.args[1] = qcom_tzmem_to_phys(input_rt_buf);
792+
desc.args[1] = qcom_tzmem_to_phys(input_rt_tzm);
826793
desc.args[2] = input_rt_size;
827-
desc.args[3] = qcom_tzmem_to_phys(output_rt_buf);
794+
desc.args[3] = qcom_tzmem_to_phys(output_rt_tzm);
828795
desc.args[4] = *output_rt_size;
829796

830797
/*
831798
* Whether SMC fail or pass, res.result[2] will hold actual resource table
832799
* size.
833800
*
834-
* if passed 'output_rt_size' buffer size is not sufficient to hold the
801+
* If passed 'output_rt_size' buffer size is not sufficient to hold the
835802
* resource table TrustZone sends, response code in res.result[1] as
836-
* RSCTABLE_BUFFER_NOT_SUFFICIENT so that caller can retry this SMC call with
837-
* output_rt buffer with res.result[2] size.
803+
* RSCTABLE_BUFFER_NOT_SUFFICIENT so that caller can retry this SMC call
804+
* with output_rt_tzm buffer with res.result[2] size however, It should not
805+
* be of unresonable size.
838806
*/
839807
ret = qcom_scm_call(__scm->dev, &desc, &res);
840-
*output_rt_size = res.result[2];
841-
if (!ret)
842-
memcpy(*output_rt, output_rt_buf, *output_rt_size);
808+
if (!ret && res.result[2] > SZ_1G) {
809+
ret = -E2BIG;
810+
goto free_output_rt;
811+
}
843812

813+
*output_rt_size = res.result[2];
844814
if (ret && res.result[1] == RSCTABLE_BUFFER_NOT_SUFFICIENT)
845-
ret = -EAGAIN;
846-
847-
qcom_tzmem_free(output_rt_buf);
848-
849-
free_input_rt_buf:
850-
qcom_tzmem_free(input_rt_buf);
815+
ret = -EOVERFLOW;
851816

852-
disable_scm_bw:
853-
qcom_scm_bw_disable();
854-
855-
disable_clk:
856-
qcom_scm_clk_disable();
817+
free_output_rt:
818+
if (ret)
819+
qcom_tzmem_free(output_rt_tzm);
857820

858-
return ret ? : res.result[0];
821+
return ret ? ERR_PTR(ret) : output_rt_tzm;
859822
}
860823

861824
/**
@@ -877,7 +840,7 @@ static int __qcom_scm_pas_get_rsc_table(u32 pas_id, void *input_rt, size_t input
877840
* If the remote processor firmware binary does contain static resources, they
878841
* should be passed in input_rt. These will be forwarded to TrustZone for
879842
* authentication. TrustZone will then append the dynamic resources and return
880-
* the complete resource table in output_rt.
843+
* the complete resource table in output_rt_tzm.
881844
*
882845
* If the remote processor firmware binary does not include a resource table,
883846
* the caller of this function should set input_rt as NULL and input_rt_size
@@ -890,37 +853,87 @@ static int __qcom_scm_pas_get_rsc_table(u32 pas_id, void *input_rt, size_t input
890853
* @pas_id: peripheral authentication service id
891854
* @input_rt: resource table buffer which is present in firmware binary
892855
* @input_rt_size: size of the resource table present in firmware binary
893-
* @output_rt: buffer to which the both static and dynamic resources will
894-
* be returned.
895856
* @output_rt_size: TrustZone expects caller should pass worst case size for
896-
* the output_rt.
897-
*
898-
* Return: 0 on success and nonzero on failure.
857+
* the output_rt_tzm.
899858
*
900-
* Upon successful return, output_rt will have the resource table and output_rt_size
901-
* will have actual resource table size,
859+
* Return:
860+
* On success, returns a pointer to the allocated buffer containing the final
861+
* resource table and output_rt_size will have actual resource table size from
862+
* TrustZone. The caller is responsible for freeing the buffer. On failure,
863+
* returns ERR_PTR(-errno).
902864
*/
903-
int qcom_scm_pas_get_rsc_table(struct qcom_scm_pas_context *ctx, void *input_rt,
904-
size_t input_rt_size, void **output_rt,
905-
size_t *output_rt_size)
906-
{
907-
unsigned int retry_num = 5;
865+
struct resource_table *qcom_scm_pas_get_rsc_table(struct qcom_scm_pas_context *ctx,
866+
void *input_rt,
867+
size_t input_rt_size,
868+
size_t *output_rt_size)
869+
{
870+
struct resource_table empty_rsc = {};
871+
size_t size = SZ_16K;
872+
void *output_rt_tzm;
873+
void *input_rt_tzm;
874+
void *tbl_ptr;
908875
int ret;
909876

910-
do {
911-
*output_rt = kzalloc(*output_rt_size, GFP_KERNEL);
912-
if (!*output_rt)
913-
return -ENOMEM;
877+
ret = qcom_scm_clk_enable();
878+
if (ret)
879+
return ERR_PTR(ret);
914880

915-
ret = __qcom_scm_pas_get_rsc_table(ctx->pas_id, input_rt,
916-
input_rt_size, output_rt,
917-
output_rt_size);
918-
if (ret)
919-
kfree(*output_rt);
881+
ret = qcom_scm_bw_enable();
882+
if (ret)
883+
goto disable_clk;
884+
885+
/*
886+
* TrustZone can not accept buffer as NULL value as argument hence,
887+
* we need to pass a input buffer indicating that subsystem firmware
888+
* does not have resource table by filling resource table structure.
889+
*/
890+
if (!input_rt) {
891+
input_rt = &empty_rsc;
892+
input_rt_size = sizeof(empty_rsc);
893+
}
894+
895+
input_rt_tzm = qcom_tzmem_alloc(__scm->mempool, input_rt_size, GFP_KERNEL);
896+
if (!input_rt_tzm) {
897+
ret = -ENOMEM;
898+
goto disable_scm_bw;
899+
}
920900

921-
} while (ret == -EAGAIN && --retry_num);
901+
memcpy(input_rt_tzm, input_rt, input_rt_size);
902+
903+
output_rt_tzm = __qcom_scm_pas_get_rsc_table(ctx->pas_id, input_rt_tzm,
904+
input_rt_size, &size);
905+
if (PTR_ERR(output_rt_tzm) == -EOVERFLOW)
906+
/* Try again with the size requested by the TZ */
907+
output_rt_tzm = __qcom_scm_pas_get_rsc_table(ctx->pas_id,
908+
input_rt_tzm,
909+
input_rt_size,
910+
&size);
911+
if (IS_ERR(output_rt_tzm)) {
912+
ret = PTR_ERR(output_rt_tzm);
913+
goto free_input_rt;
914+
}
922915

923-
return ret;
916+
tbl_ptr = kzalloc(size, GFP_KERNEL);
917+
if (!tbl_ptr) {
918+
qcom_tzmem_free(output_rt_tzm);
919+
ret = -ENOMEM;
920+
goto free_input_rt;
921+
}
922+
923+
memcpy(tbl_ptr, output_rt_tzm, size);
924+
*output_rt_size = size;
925+
qcom_tzmem_free(output_rt_tzm);
926+
927+
free_input_rt:
928+
qcom_tzmem_free(input_rt_tzm);
929+
930+
disable_scm_bw:
931+
qcom_scm_bw_disable();
932+
933+
disable_clk:
934+
qcom_scm_clk_disable();
935+
936+
return ret ? ERR_PTR(ret) : tbl_ptr;
924937
}
925938
EXPORT_SYMBOL_GPL(qcom_scm_pas_get_rsc_table);
926939

@@ -985,22 +998,21 @@ int qcom_scm_pas_prepare_and_auth_reset(struct qcom_scm_pas_context *ctx)
985998
u64 handle;
986999
int ret;
9871000

988-
if (!ctx->has_iommu)
989-
return qcom_scm_pas_auth_and_reset(ctx->pas_id);
990-
9911001
/*
9921002
* When Linux running @ EL1, Gunyah hypervisor running @ EL2 traps the
9931003
* auth_and_reset call and create an shmbridge on the remote subsystem
9941004
* memory region and then invokes a call to TrustZone to authenticate.
1005+
*/
1006+
if (!ctx->use_tzmem)
1007+
return qcom_scm_pas_auth_and_reset(ctx->pas_id);
1008+
1009+
/*
9951010
* When Linux runs @ EL2 Linux must create the shmbridge itself and then
9961011
* subsequently call TrustZone for authenticate and reset.
9971012
*/
9981013
ret = qcom_tzmem_shm_bridge_create(ctx->mem_phys, ctx->mem_size, &handle);
999-
if (ret) {
1000-
dev_err(__scm->dev, "Failed to create shmbridge for PAS ID (%u): %d\n",
1001-
ctx->pas_id, ret);
1014+
if (ret)
10021015
return ret;
1003-
}
10041016

10051017
ret = qcom_scm_pas_auth_and_reset(ctx->pas_id);
10061018
qcom_tzmem_shm_bridge_delete(handle);

drivers/remoteproc/qcom_q6v5_pas.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
#define QCOM_PAS_DECRYPT_SHUTDOWN_DELAY_MS 100
3636

3737
#define MAX_ASSIGN_COUNT 3
38-
#define MAX_RSCTABLE_SIZE SZ_16K
3938

4039
struct qcom_pas_data {
4140
int crash_reason_smem;
@@ -451,9 +450,9 @@ static void *qcom_pas_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is
451450

452451
static int qcom_pas_parse_firmware(struct rproc *rproc, const struct firmware *fw)
453452
{
454-
size_t output_rt_size = MAX_RSCTABLE_SIZE;
455453
struct qcom_pas *pas = rproc->priv;
456454
struct resource_table *table = NULL;
455+
size_t output_rt_size;
457456
void *output_rt;
458457
size_t table_sz;
459458
int ret;
@@ -489,8 +488,8 @@ static int qcom_pas_parse_firmware(struct rproc *rproc, const struct firmware *f
489488
* and this is even true for Qualcomm remote processor who does follow remoteproc
490489
* framework.
491490
*/
492-
ret = qcom_scm_pas_get_rsc_table(pas->pas_ctx, table, table_sz, &output_rt,
493-
&output_rt_size);
491+
output_rt = qcom_scm_pas_get_rsc_table(pas->pas_ctx, table, table_sz, &output_rt_size);
492+
ret = IS_ERR(output_rt) ? PTR_ERR(output_rt) : 0;
494493
if (ret) {
495494
dev_err(pas->dev, "Error in getting resource table: %d\n", ret);
496495
return ret;
@@ -858,23 +857,23 @@ static int qcom_pas_probe(struct platform_device *pdev)
858857

859858
qcom_add_ssr_subdev(rproc, &pas->ssr_subdev, desc->ssr_name);
860859

861-
pas->pas_ctx = devm_qcom_scm_pas_context_init(pas->dev, pas->pas_id,
862-
pas->mem_phys, pas->mem_size);
860+
pas->pas_ctx = devm_qcom_scm_pas_context_alloc(pas->dev, pas->pas_id,
861+
pas->mem_phys, pas->mem_size);
863862
if (IS_ERR(pas->pas_ctx)) {
864863
ret = PTR_ERR(pas->pas_ctx);
865864
goto remove_ssr_sysmon;
866865
}
867866

868-
pas->dtb_pas_ctx = devm_qcom_scm_pas_context_init(pas->dev, pas->dtb_pas_id,
869-
pas->dtb_mem_phys,
870-
pas->dtb_mem_size);
867+
pas->dtb_pas_ctx = devm_qcom_scm_pas_context_alloc(pas->dev, pas->dtb_pas_id,
868+
pas->dtb_mem_phys,
869+
pas->dtb_mem_size);
871870
if (IS_ERR(pas->dtb_pas_ctx)) {
872871
ret = PTR_ERR(pas->dtb_pas_ctx);
873872
goto remove_ssr_sysmon;
874873
}
875874

876-
pas->pas_ctx->has_iommu = rproc->has_iommu;
877-
pas->dtb_pas_ctx->has_iommu = rproc->has_iommu;
875+
pas->pas_ctx->use_tzmem = rproc->has_iommu;
876+
pas->dtb_pas_ctx->use_tzmem = rproc->has_iommu;
878877
ret = rproc_add(rproc);
879878
if (ret)
880879
goto remove_ssr_sysmon;

0 commit comments

Comments
 (0)