diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c index 07e2553546c7..a236787fb99f 100644 --- a/drivers/soc/qcom/peripheral-loader.c +++ b/drivers/soc/qcom/peripheral-loader.c @@ -101,45 +101,6 @@ struct pil_seg { bool relocated; }; -/** - * struct pil_priv - Private state for a pil_desc - * @proxy: work item used to run the proxy unvoting routine - * @ws: wakeup source to prevent suspend during pil_boot - * @wname: name of @ws - * @desc: pointer to pil_desc this is private data for - * @seg: list of segments sorted by physical address - * @entry_addr: physical address where processor starts booting at - * @base_addr: smallest start address among all segments that are relocatable - * @region_start: address where relocatable region starts or lowest address - * for non-relocatable images - * @region_end: address where relocatable region ends or highest address for - * non-relocatable images - * @region: region allocated for relocatable images - * @unvoted_flag: flag to keep track if we have unvoted or not. - * - * This struct contains data for a pil_desc that should not be exposed outside - * of this file. This structure points to the descriptor and the descriptor - * points to this structure so that PIL drivers can't access the private - * data of a descriptor but this file can access both. - */ -struct pil_priv { - struct delayed_work proxy; - struct wakeup_source *ws; - char wname[32]; - struct pil_desc *desc; - int num_segs; - struct list_head segs; - phys_addr_t entry_addr; - phys_addr_t base_addr; - phys_addr_t region_start; - phys_addr_t region_end; - bool is_region_allocated; - struct pil_image_info __iomem *info; - int id; - int unvoted_flag; - size_t region_size; -}; - /** * struct aux_minidumpinfo - State maintained for each aux minidump entry dumped * during SSR diff --git a/drivers/soc/qcom/peripheral-loader.h b/drivers/soc/qcom/peripheral-loader.h index 57180c739f17..a5ddfb04c3af 100644 --- a/drivers/soc/qcom/peripheral-loader.h +++ b/drivers/soc/qcom/peripheral-loader.h @@ -9,9 +9,47 @@ #include #include "minidump_private.h" +#define SECURE_PAGE_MAGIC 0xEEEEEEEE struct device; struct module; -struct pil_priv; +/** + * struct pil_priv - Private state for a pil_desc + * @proxy: work item used to run the proxy unvoting routine + * @ws: wakeup source to prevent suspend during pil_boot + * @wname: name of @ws + * @desc: pointer to pil_desc this is private data for + * @seg: list of segments sorted by physical address + * @entry_addr: physical address where processor starts booting at + * @base_addr: smallest start address among all segments that are relocatable + * @region_start: address where relocatable region starts or lowest address + * for non-relocatable images + * @region_end: address where relocatable region ends or highest address for + * non-relocatable images + * @region: region allocated for relocatable images + * @unvoted_flag: flag to keep track if we have unvoted or not. + * + * This struct contains data for a pil_desc that should not be exposed outside + * of this file. This structure points to the descriptor and the descriptor + * points to this structure so that PIL drivers can't access the private + * data of a descriptor but this file can access both. + */ +struct pil_priv { + struct delayed_work proxy; + struct wakeup_source *ws; + char wname[32]; + struct pil_desc *desc; + int num_segs; + struct list_head segs; + phys_addr_t entry_addr; + phys_addr_t base_addr; + phys_addr_t region_start; + phys_addr_t region_end; + bool is_region_allocated; + struct pil_image_info __iomem *info; + int id; + int unvoted_flag; + size_t region_size; +}; /** * struct pil_desc - PIL descriptor diff --git a/drivers/soc/qcom/subsys-pil-tz.c b/drivers/soc/qcom/subsys-pil-tz.c index 71cbf3a26de7..b8be316a1e2f 100644 --- a/drivers/soc/qcom/subsys-pil-tz.c +++ b/drivers/soc/qcom/subsys-pil-tz.c @@ -629,6 +629,7 @@ static int pil_auth_and_reset(struct pil_desc *pil) struct pil_tz_data *d = desc_to_data(pil); int rc; u32 scm_ret = 0; + unsigned long pfn_start, pfn_end, pfn; if (d->subsys_desc.no_auth) return 0; @@ -647,6 +648,14 @@ static int pil_auth_and_reset(struct pil_desc *pil) scm_ret = qcom_scm_pas_auth_and_reset(d->pas_id); + pfn_start = pil->priv->region_start >> PAGE_SHIFT; + if (pfn_valid(pfn_start) && !scm_ret) { + pfn_end = (PAGE_ALIGN(pil->priv->region_start + + pil->priv->region_size)) >> PAGE_SHIFT; + for (pfn = pfn_start; pfn < pfn_end; pfn++) + set_page_private(pfn_to_page(pfn), SECURE_PAGE_MAGIC); + } + scm_pas_disable_bw(); if (rc) goto err_reset; @@ -665,6 +674,7 @@ static int pil_shutdown_trusted(struct pil_desc *pil) struct pil_tz_data *d = desc_to_data(pil); u32 scm_ret = 0; int rc; + unsigned long pfn_start, pfn_end, pfn; if (d->subsys_desc.no_auth) return 0; @@ -685,6 +695,14 @@ static int pil_shutdown_trusted(struct pil_desc *pil) scm_ret = qcom_scm_pas_shutdown(d->pas_id); + pfn_start = pil->priv->region_start >> PAGE_SHIFT; + if (pfn_valid(pfn_start) && !scm_ret) { + pfn_end = (PAGE_ALIGN(pil->priv->region_start + + pil->priv->region_size)) >> PAGE_SHIFT; + for (pfn = pfn_start; pfn < pfn_end; pfn++) + set_page_private(pfn_to_page(pfn), 0); + } + disable_unprepare_clocks(d->proxy_clks, d->proxy_clk_count); disable_regulators(d, d->proxy_regs, d->proxy_reg_count, false); @@ -709,11 +727,22 @@ err_regulators: static int pil_deinit_image_trusted(struct pil_desc *pil) { struct pil_tz_data *d = desc_to_data(pil); + u32 scm_ret = 0; + unsigned long pfn_start, pfn_end, pfn; if (d->subsys_desc.no_auth) return 0; - return qcom_scm_pas_shutdown(d->pas_id); + scm_ret = qcom_scm_pas_shutdown(d->pas_id); + pfn_start = pil->priv->region_start >> PAGE_SHIFT; + if (pfn_valid(pfn_start) && !scm_ret) { + pfn_end = (PAGE_ALIGN(pil->priv->region_start + + pil->priv->region_size)) >> PAGE_SHIFT; + for (pfn = pfn_start; pfn < pfn_end; pfn++) + set_page_private(pfn_to_page(pfn), 0); + } + + return scm_ret; } static struct pil_reset_ops pil_ops_trusted = {