Loading Documentation/devicetree/bindings/arm/msm/imem.txt +10 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,11 @@ USB Diag Cookies: Memory region used to store USB PID and serial numbers to be used by bootloader in download mode. SSR Minidump Offset ------------------- -Compatible: "qcom,msm-imem-minidump" -reg: start address and size of ssr imem region Required properties: -compatible: "qcom,msm-imem-diag-dload" -reg: start address and size of USB Diag download mode region in imem Loading Loading @@ -121,4 +126,9 @@ Example: compatible = "qcom,msm-imem-emergency_download_mode"; reg = <0xfe0 12>; }; ss_mdump@b88 { compatible = "qcom,msm-imem-minidump"; reg = <0xb88 28>; }; }; drivers/soc/qcom/peripheral-loader.c +108 −1 Original line number Diff line number Diff line Loading @@ -56,7 +56,10 @@ #define PIL_NUM_DESC 10 #define MAX_LEN 96 #define NUM_OF_ENCRYPTED_KEY 3 static void __iomem *pil_info_base; static void __iomem *pil_minidump_base; /** * proxy_timeout - Override for proxy vote timeouts Loading @@ -78,6 +81,18 @@ struct pil_mdt { struct elf32_phdr phdr[]; }; /** * struct boot_minidump_smem_region - Representation of SMEM TOC * @region_name: Name of modem segment to be dumped * @region_base_address: Where segment start from * @region_size: Size of segment to be dumped */ struct boot_minidump_smem_region { char region_name[16]; u64 region_base_address; u64 region_size; }; /** * struct pil_seg - memory map representing one segment * @next: points to next seg mentor NULL if last segment Loading Loading @@ -132,11 +147,67 @@ struct pil_priv { phys_addr_t region_end; void *region; struct pil_image_info __iomem *info; struct md_ssr_ss_info __iomem *minidump; int minidump_id; int id; int unvoted_flag; size_t region_size; }; static int pil_do_minidump(struct pil_desc *desc, void *ramdump_dev) { struct boot_minidump_smem_region __iomem *region_info; struct ramdump_segment *ramdump_segs, *s; struct pil_priv *priv = desc->priv; void __iomem *subsys_smem_base; void __iomem *offset; int ss_mdump_seg_cnt; int ret, i; memcpy(&offset, &priv->minidump, sizeof(priv->minidump)); offset = offset + sizeof(priv->minidump->md_ss_smem_regions_baseptr); /* There are 3 encryption keys which also need to be dumped */ ss_mdump_seg_cnt = readb_relaxed(offset) + NUM_OF_ENCRYPTED_KEY; subsys_smem_base = ioremap(__raw_readl(priv->minidump), ss_mdump_seg_cnt * sizeof(*region_info)); region_info = (struct boot_minidump_smem_region __iomem *)subsys_smem_base; ramdump_segs = kcalloc(ss_mdump_seg_cnt, sizeof(*ramdump_segs), GFP_KERNEL); if (!ramdump_segs) return -ENOMEM; if (desc->subsys_vmid > 0) ret = pil_assign_mem_to_linux(desc, priv->region_start, (priv->region_end - priv->region_start)); s = ramdump_segs; for (i = 0; i < ss_mdump_seg_cnt; i++) { memcpy(&offset, ®ion_info, sizeof(region_info)); memcpy(&s->name, ®ion_info, sizeof(region_info)); offset = offset + sizeof(region_info->region_name); s->address = __raw_readl(offset); offset = offset + sizeof(region_info->region_base_address); s->size = __raw_readl(offset); s++; region_info++; } ret = do_minidump(ramdump_dev, ramdump_segs, ss_mdump_seg_cnt); kfree(ramdump_segs); if (ret) pil_err(desc, "%s: Ramdump collection failed for subsys %s rc:%d\n", __func__, desc->name, ret); writel_relaxed(0, &priv->minidump->md_ss_smem_regions_baseptr); writeb_relaxed(1, &priv->minidump->md_ss_ssr_cause); if (desc->subsys_vmid > 0) ret = pil_assign_mem_to_subsys(desc, priv->region_start, (priv->region_end - priv->region_start)); return ret; } /** * pil_do_ramdump() - Ramdump an image * @desc: descriptor from pil_desc_init() Loading @@ -152,6 +223,9 @@ int pil_do_ramdump(struct pil_desc *desc, void *ramdump_dev) int count = 0, ret; struct ramdump_segment *ramdump_segs, *s; if (priv->minidump && (__raw_readl(priv->minidump) > 0)) return pil_do_minidump(desc, ramdump_dev); list_for_each_entry(seg, &priv->segs, list) count++; Loading Loading @@ -1041,9 +1115,10 @@ bool is_timeout_disabled(void) int pil_desc_init(struct pil_desc *desc) { struct pil_priv *priv; int ret; void __iomem *addr; int ret, ss_imem_offset_mdump; char buf[sizeof(priv->info->name)]; struct device_node *ofnode = desc->dev->of_node; if (WARN(desc->ops->proxy_unvote && !desc->ops->proxy_vote, "Invalid proxy voting. Ignoring\n")) Loading @@ -1066,6 +1141,22 @@ int pil_desc_init(struct pil_desc *desc) strlcpy(buf, desc->name, sizeof(buf)); __iowrite32_copy(priv->info->name, buf, sizeof(buf) / 4); } if (of_property_read_u32(ofnode, "qcom,minidump-id", &priv->minidump_id)) pr_debug("minidump-id not found for %s\n", desc->name); else { ss_imem_offset_mdump = sizeof(struct md_ssr_ss_info) * priv->minidump_id; if (pil_minidump_base) { /* Add 0x4 to get start of struct md_ssr_ss_info base * from struct md_ssr_toc for any subsystem, * struct md_ssr_ss_info is actually the pointer * of ToC in smem for any subsystem. */ addr = pil_minidump_base + ss_imem_offset_mdump + 0x4; priv->minidump = (struct md_ssr_ss_info __iomem *)addr; } } ret = pil_parse_devicetree(desc); if (ret) Loading Loading @@ -1174,6 +1265,20 @@ static int __init msm_pil_init(void) for (i = 0; i < resource_size(&res)/sizeof(u32); i++) writel_relaxed(0, pil_info_base + (i * sizeof(u32))); np = of_find_compatible_node(NULL, NULL, "qcom,msm-imem-minidump"); if (!np) { pr_warn("pil: failed to find qcom,msm-imem-minidump node\n"); goto out; } else { pil_minidump_base = of_iomap(np, 0); if (!pil_minidump_base) { pr_err("unable to map pil minidump imem offset\n"); goto out; } } for (i = 0; i < sizeof(struct md_ssr_toc)/sizeof(u32); i++) writel_relaxed(0, pil_minidump_base + (i * sizeof(u32))); writel_relaxed(1, pil_minidump_base); out: return register_pm_notifier(&pil_pm_notifier); } Loading @@ -1184,6 +1289,8 @@ static void __exit msm_pil_exit(void) unregister_pm_notifier(&pil_pm_notifier); if (pil_info_base) iounmap(pil_info_base); if (pil_minidump_base) iounmap(pil_minidump_base); } module_exit(msm_pil_exit); Loading drivers/soc/qcom/peripheral-loader.h +28 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,34 @@ struct pil_image_info { __le32 size; } __attribute__((__packed__)); #define MAX_NUM_OF_SS 3 /** * struct md_ssr_ss_info - Info in imem about smem ToC * @md_ss_smem_regions_baseptr: Start physical address of SMEM TOC * @md_ss_num_of_regions: number of segments that need to be dumped * @md_ss_encryption_status: status of encryption of segments * @md_ss_ssr_cause: ssr cause enum */ struct md_ssr_ss_info { u32 md_ss_smem_regions_baseptr; u8 md_ss_num_of_regions; u8 md_ss_encryption_status; u8 md_ss_ssr_cause; u8 reserved; }; /** * struct md_ssr_toc - Wrapper of struct md_ssr_ss_info * @md_ssr_toc_init: flag to indicate to MSS SW about imem init done * @md_ssr_ss: Instance of struct md_ssr_ss_info for a subsystem */ struct md_ssr_toc /* Shared IMEM ToC struct */ { u32 md_ssr_toc_init; struct md_ssr_ss_info md_ssr_ss[MAX_NUM_OF_SS]; }; /** * struct pil_reset_ops - PIL operations * @init_image: prepare an image for authentication Loading include/soc/qcom/ramdump.h +2 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ extern int do_ramdump(void *handle, struct ramdump_segment *segments, int nsegments); extern int do_elf_ramdump(void *handle, struct ramdump_segment *segments, int nsegments); extern int do_minidump(void *handle, struct ramdump_segment *segments, int nsegments); #else static inline void *create_ramdump_device(const char *dev_name, Loading Loading
Documentation/devicetree/bindings/arm/msm/imem.txt +10 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,11 @@ USB Diag Cookies: Memory region used to store USB PID and serial numbers to be used by bootloader in download mode. SSR Minidump Offset ------------------- -Compatible: "qcom,msm-imem-minidump" -reg: start address and size of ssr imem region Required properties: -compatible: "qcom,msm-imem-diag-dload" -reg: start address and size of USB Diag download mode region in imem Loading Loading @@ -121,4 +126,9 @@ Example: compatible = "qcom,msm-imem-emergency_download_mode"; reg = <0xfe0 12>; }; ss_mdump@b88 { compatible = "qcom,msm-imem-minidump"; reg = <0xb88 28>; }; };
drivers/soc/qcom/peripheral-loader.c +108 −1 Original line number Diff line number Diff line Loading @@ -56,7 +56,10 @@ #define PIL_NUM_DESC 10 #define MAX_LEN 96 #define NUM_OF_ENCRYPTED_KEY 3 static void __iomem *pil_info_base; static void __iomem *pil_minidump_base; /** * proxy_timeout - Override for proxy vote timeouts Loading @@ -78,6 +81,18 @@ struct pil_mdt { struct elf32_phdr phdr[]; }; /** * struct boot_minidump_smem_region - Representation of SMEM TOC * @region_name: Name of modem segment to be dumped * @region_base_address: Where segment start from * @region_size: Size of segment to be dumped */ struct boot_minidump_smem_region { char region_name[16]; u64 region_base_address; u64 region_size; }; /** * struct pil_seg - memory map representing one segment * @next: points to next seg mentor NULL if last segment Loading Loading @@ -132,11 +147,67 @@ struct pil_priv { phys_addr_t region_end; void *region; struct pil_image_info __iomem *info; struct md_ssr_ss_info __iomem *minidump; int minidump_id; int id; int unvoted_flag; size_t region_size; }; static int pil_do_minidump(struct pil_desc *desc, void *ramdump_dev) { struct boot_minidump_smem_region __iomem *region_info; struct ramdump_segment *ramdump_segs, *s; struct pil_priv *priv = desc->priv; void __iomem *subsys_smem_base; void __iomem *offset; int ss_mdump_seg_cnt; int ret, i; memcpy(&offset, &priv->minidump, sizeof(priv->minidump)); offset = offset + sizeof(priv->minidump->md_ss_smem_regions_baseptr); /* There are 3 encryption keys which also need to be dumped */ ss_mdump_seg_cnt = readb_relaxed(offset) + NUM_OF_ENCRYPTED_KEY; subsys_smem_base = ioremap(__raw_readl(priv->minidump), ss_mdump_seg_cnt * sizeof(*region_info)); region_info = (struct boot_minidump_smem_region __iomem *)subsys_smem_base; ramdump_segs = kcalloc(ss_mdump_seg_cnt, sizeof(*ramdump_segs), GFP_KERNEL); if (!ramdump_segs) return -ENOMEM; if (desc->subsys_vmid > 0) ret = pil_assign_mem_to_linux(desc, priv->region_start, (priv->region_end - priv->region_start)); s = ramdump_segs; for (i = 0; i < ss_mdump_seg_cnt; i++) { memcpy(&offset, ®ion_info, sizeof(region_info)); memcpy(&s->name, ®ion_info, sizeof(region_info)); offset = offset + sizeof(region_info->region_name); s->address = __raw_readl(offset); offset = offset + sizeof(region_info->region_base_address); s->size = __raw_readl(offset); s++; region_info++; } ret = do_minidump(ramdump_dev, ramdump_segs, ss_mdump_seg_cnt); kfree(ramdump_segs); if (ret) pil_err(desc, "%s: Ramdump collection failed for subsys %s rc:%d\n", __func__, desc->name, ret); writel_relaxed(0, &priv->minidump->md_ss_smem_regions_baseptr); writeb_relaxed(1, &priv->minidump->md_ss_ssr_cause); if (desc->subsys_vmid > 0) ret = pil_assign_mem_to_subsys(desc, priv->region_start, (priv->region_end - priv->region_start)); return ret; } /** * pil_do_ramdump() - Ramdump an image * @desc: descriptor from pil_desc_init() Loading @@ -152,6 +223,9 @@ int pil_do_ramdump(struct pil_desc *desc, void *ramdump_dev) int count = 0, ret; struct ramdump_segment *ramdump_segs, *s; if (priv->minidump && (__raw_readl(priv->minidump) > 0)) return pil_do_minidump(desc, ramdump_dev); list_for_each_entry(seg, &priv->segs, list) count++; Loading Loading @@ -1041,9 +1115,10 @@ bool is_timeout_disabled(void) int pil_desc_init(struct pil_desc *desc) { struct pil_priv *priv; int ret; void __iomem *addr; int ret, ss_imem_offset_mdump; char buf[sizeof(priv->info->name)]; struct device_node *ofnode = desc->dev->of_node; if (WARN(desc->ops->proxy_unvote && !desc->ops->proxy_vote, "Invalid proxy voting. Ignoring\n")) Loading @@ -1066,6 +1141,22 @@ int pil_desc_init(struct pil_desc *desc) strlcpy(buf, desc->name, sizeof(buf)); __iowrite32_copy(priv->info->name, buf, sizeof(buf) / 4); } if (of_property_read_u32(ofnode, "qcom,minidump-id", &priv->minidump_id)) pr_debug("minidump-id not found for %s\n", desc->name); else { ss_imem_offset_mdump = sizeof(struct md_ssr_ss_info) * priv->minidump_id; if (pil_minidump_base) { /* Add 0x4 to get start of struct md_ssr_ss_info base * from struct md_ssr_toc for any subsystem, * struct md_ssr_ss_info is actually the pointer * of ToC in smem for any subsystem. */ addr = pil_minidump_base + ss_imem_offset_mdump + 0x4; priv->minidump = (struct md_ssr_ss_info __iomem *)addr; } } ret = pil_parse_devicetree(desc); if (ret) Loading Loading @@ -1174,6 +1265,20 @@ static int __init msm_pil_init(void) for (i = 0; i < resource_size(&res)/sizeof(u32); i++) writel_relaxed(0, pil_info_base + (i * sizeof(u32))); np = of_find_compatible_node(NULL, NULL, "qcom,msm-imem-minidump"); if (!np) { pr_warn("pil: failed to find qcom,msm-imem-minidump node\n"); goto out; } else { pil_minidump_base = of_iomap(np, 0); if (!pil_minidump_base) { pr_err("unable to map pil minidump imem offset\n"); goto out; } } for (i = 0; i < sizeof(struct md_ssr_toc)/sizeof(u32); i++) writel_relaxed(0, pil_minidump_base + (i * sizeof(u32))); writel_relaxed(1, pil_minidump_base); out: return register_pm_notifier(&pil_pm_notifier); } Loading @@ -1184,6 +1289,8 @@ static void __exit msm_pil_exit(void) unregister_pm_notifier(&pil_pm_notifier); if (pil_info_base) iounmap(pil_info_base); if (pil_minidump_base) iounmap(pil_minidump_base); } module_exit(msm_pil_exit); Loading
drivers/soc/qcom/peripheral-loader.h +28 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,34 @@ struct pil_image_info { __le32 size; } __attribute__((__packed__)); #define MAX_NUM_OF_SS 3 /** * struct md_ssr_ss_info - Info in imem about smem ToC * @md_ss_smem_regions_baseptr: Start physical address of SMEM TOC * @md_ss_num_of_regions: number of segments that need to be dumped * @md_ss_encryption_status: status of encryption of segments * @md_ss_ssr_cause: ssr cause enum */ struct md_ssr_ss_info { u32 md_ss_smem_regions_baseptr; u8 md_ss_num_of_regions; u8 md_ss_encryption_status; u8 md_ss_ssr_cause; u8 reserved; }; /** * struct md_ssr_toc - Wrapper of struct md_ssr_ss_info * @md_ssr_toc_init: flag to indicate to MSS SW about imem init done * @md_ssr_ss: Instance of struct md_ssr_ss_info for a subsystem */ struct md_ssr_toc /* Shared IMEM ToC struct */ { u32 md_ssr_toc_init; struct md_ssr_ss_info md_ssr_ss[MAX_NUM_OF_SS]; }; /** * struct pil_reset_ops - PIL operations * @init_image: prepare an image for authentication Loading
include/soc/qcom/ramdump.h +2 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ extern int do_ramdump(void *handle, struct ramdump_segment *segments, int nsegments); extern int do_elf_ramdump(void *handle, struct ramdump_segment *segments, int nsegments); extern int do_minidump(void *handle, struct ramdump_segment *segments, int nsegments); #else static inline void *create_ramdump_device(const char *dev_name, Loading