Skip to content

Commit 8988946

Browse files
FROMLIST: remoteproc: qcom: pas: Map/unmap subsystem region before auth_and_reset
Qualcomm remoteproc drivers such as qcom_q6v5_mss, which do not use the Peripheral Authentication Service (PAS), always map the MBA region before use and unmap it once the usage is complete. This behavior was introduced to avoid issues seen in the past where speculative accesses from the application processor to the MBA region after it was assigned to the remote Q6 led to an XPU violation. The issue was mitigated by unmapping the region before handing control to the remote Q6. Currently, most Qualcomm SoCs using the PAS driver run either with a standalone QHEE or the Gunyah hypervisor. In these environments, the hypervisor unmaps the Q6 memory from HLOS Stage-2 and remaps it into the Q6 Stage-2 page table. As a result, speculative accesses from HLOS cannot reach the region even if it remains mapped in HLOS Stage-1; therefore, XPU violations cannot occur. However, when the same SoC runs Linux at EL2, Linux itself must perform the unmapping to avoid such issues. It is still correct to apply this mapping/ unmapping sequence even for SoCs that run under Gunyah, so this behavior should not be conditional. Link: https://lore.kernel.org/lkml/20260325191301.164579-2-mukesh.ojha@oss.qualcomm.com/ Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
1 parent 038ee40 commit 8988946

4 files changed

Lines changed: 45 additions & 23 deletions

File tree

drivers/media/platform/qcom/iris/iris_firmware.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name)
7272
goto err_release_fw;
7373
}
7474

75-
ret = qcom_mdt_pas_load(ctx, firmware, fw_name, mem_virt, NULL);
75+
ret = qcom_mdt_pas_load(ctx, firmware, fw_name, NULL);
7676
qcom_scm_pas_metadata_release(ctx);
7777
if (ret)
7878
goto err_mem_unmap;

drivers/remoteproc/qcom_q6v5_pas.c

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,16 @@ static void qcom_pas_minidump(struct rproc *rproc)
148148
if (rproc->dump_conf == RPROC_COREDUMP_DISABLED)
149149
return;
150150

151+
pas->mem_region = ioremap_wc(pas->mem_phys, pas->mem_size);
152+
if (!pas->mem_region) {
153+
dev_err(pas->dev, "unable to map memory region: %pa+%zx\n",
154+
&pas->mem_phys, pas->mem_size);
155+
return;
156+
}
157+
151158
qcom_minidump(rproc, pas->minidump_id, qcom_pas_segment_dump);
159+
iounmap(pas->mem_region);
160+
pas->mem_region = NULL;
152161
}
153162

154163
static int qcom_pas_pds_enable(struct qcom_pas *pas, struct device **pds,
@@ -253,7 +262,7 @@ static int qcom_pas_load(struct rproc *rproc, const struct firmware *fw)
253262
}
254263

255264
ret = qcom_mdt_pas_load(pas->dtb_pas_ctx, pas->dtb_firmware,
256-
pas->dtb_firmware_name, pas->dtb_mem_region,
265+
pas->dtb_firmware_name,
257266
&pas->dtb_mem_reloc);
258267
if (ret)
259268
goto release_dtb_metadata;
@@ -333,7 +342,7 @@ static int qcom_pas_start(struct rproc *rproc)
333342
}
334343

335344
ret = qcom_mdt_pas_load(pas->pas_ctx, pas->firmware, rproc->firmware,
336-
pas->mem_region, &pas->mem_reloc);
345+
&pas->mem_reloc);
337346
if (ret)
338347
goto release_pas_metadata;
339348

@@ -524,6 +533,22 @@ static unsigned long qcom_pas_panic(struct rproc *rproc)
524533
return qcom_q6v5_panic(&pas->q6v5);
525534
}
526535

536+
static void qcom_pas_coredump(struct rproc *rproc)
537+
{
538+
struct qcom_pas *pas = rproc->priv;
539+
540+
pas->mem_region = ioremap_wc(pas->mem_phys, pas->mem_size);
541+
if (!pas->mem_region) {
542+
dev_err(pas->dev, "unable to map memory region: %pa+%zx\n",
543+
&pas->mem_phys, pas->mem_size);
544+
return;
545+
}
546+
547+
rproc_coredump(rproc);
548+
iounmap(pas->mem_region);
549+
pas->mem_region = NULL;
550+
}
551+
527552
static const struct rproc_ops qcom_pas_ops = {
528553
.unprepare = qcom_pas_unprepare,
529554
.start = qcom_pas_start,
@@ -532,6 +557,7 @@ static const struct rproc_ops qcom_pas_ops = {
532557
.parse_fw = qcom_pas_parse_firmware,
533558
.load = qcom_pas_load,
534559
.panic = qcom_pas_panic,
560+
.coredump = qcom_pas_coredump,
535561
};
536562

537563
static const struct rproc_ops qcom_pas_minidump_ops = {
@@ -656,13 +682,6 @@ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas)
656682

657683
pas->mem_phys = pas->mem_reloc = rmem->base;
658684
pas->mem_size = rmem->size;
659-
pas->mem_region = devm_ioremap_wc(pas->dev, pas->mem_phys, pas->mem_size);
660-
if (!pas->mem_region) {
661-
dev_err(pas->dev, "unable to map memory region: %pa+%zx\n",
662-
&rmem->base, pas->mem_size);
663-
return -EBUSY;
664-
}
665-
666685
pas->pas_ctx = devm_qcom_scm_pas_context_alloc(pas->dev, pas->pas_id,
667686
pas->mem_phys, pas->mem_size);
668687
if (IS_ERR(pas->pas_ctx))
@@ -687,13 +706,6 @@ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas)
687706

688707
pas->dtb_mem_phys = pas->dtb_mem_reloc = rmem->base;
689708
pas->dtb_mem_size = rmem->size;
690-
pas->dtb_mem_region = devm_ioremap_wc(pas->dev, pas->dtb_mem_phys, pas->dtb_mem_size);
691-
if (!pas->dtb_mem_region) {
692-
dev_err(pas->dev, "unable to map dtb memory region: %pa+%zx\n",
693-
&rmem->base, pas->dtb_mem_size);
694-
return -EBUSY;
695-
}
696-
697709
pas->dtb_pas_ctx = devm_qcom_scm_pas_context_alloc(pas->dev, pas->dtb_pas_id,
698710
pas->dtb_mem_phys,
699711
pas->dtb_mem_size);

drivers/soc/qcom/mdt_loader.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/device.h>
1212
#include <linux/elf.h>
1313
#include <linux/firmware.h>
14+
#include <linux/io.h>
1415
#include <linux/kernel.h>
1516
#include <linux/module.h>
1617
#include <linux/firmware/qcom/qcom_scm.h>
@@ -486,22 +487,31 @@ EXPORT_SYMBOL_GPL(qcom_mdt_load_no_init);
486487
* @ctx: Pointer to the PAS (Peripheral Authentication Service) context
487488
* @fw: Firmware object representing the .mdt file
488489
* @firmware: Name of the firmware used to construct segment file names
489-
* @mem_region: Memory region allocated for loading the firmware
490490
* @reloc_base: Physical address adjusted after relocation
491491
*
492492
* Return: 0 on success or a negative error code on failure.
493493
*/
494494
int qcom_mdt_pas_load(struct qcom_scm_pas_context *ctx, const struct firmware *fw,
495-
const char *firmware, void *mem_region, phys_addr_t *reloc_base)
495+
const char *firmware, phys_addr_t *reloc_base)
496496
{
497+
void *mem_region;
497498
int ret;
498499

499500
ret = __qcom_mdt_pas_init(ctx->dev, fw, firmware, ctx->pas_id, ctx->mem_phys, ctx);
500501
if (ret)
501502
return ret;
502503

503-
return qcom_mdt_load_no_init(ctx->dev, fw, firmware, mem_region, ctx->mem_phys,
504-
ctx->mem_size, reloc_base);
504+
mem_region = ioremap_wc(ctx->mem_phys, ctx->mem_size);
505+
if (!mem_region) {
506+
dev_err(ctx->dev, "unable to map memory region: %pa+%zx\n", &ctx->mem_phys,
507+
ctx->mem_size);
508+
return -EINVAL;
509+
}
510+
511+
ret = qcom_mdt_load_no_init(ctx->dev, fw, firmware, mem_region, ctx->mem_phys,
512+
ctx->mem_size, reloc_base);
513+
iounmap(mem_region);
514+
return ret;
505515
}
506516
EXPORT_SYMBOL_GPL(qcom_mdt_pas_load);
507517

include/linux/soc/qcom/mdt_loader.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ int qcom_mdt_load(struct device *dev, const struct firmware *fw,
2121
phys_addr_t *reloc_base);
2222

2323
int qcom_mdt_pas_load(struct qcom_scm_pas_context *ctx, const struct firmware *fw,
24-
const char *firmware, void *mem_region, phys_addr_t *reloc_base);
24+
const char *firmware, phys_addr_t *reloc_base);
2525

2626
int qcom_mdt_load_no_init(struct device *dev, const struct firmware *fw,
2727
const char *fw_name, void *mem_region,
@@ -47,7 +47,7 @@ static inline int qcom_mdt_load(struct device *dev, const struct firmware *fw,
4747

4848
static inline int qcom_mdt_pas_load(struct qcom_scm_pas_context *ctx,
4949
const struct firmware *fw, const char *firmware,
50-
void *mem_region, phys_addr_t *reloc_base)
50+
phys_addr_t *reloc_base)
5151
{
5252
return -ENODEV;
5353
}

0 commit comments

Comments
 (0)