浏览代码

remoteproc/k3-dsp: fix memzero issues with C66x L2SRAM

The K3 DSP remoteproc driver supports loading into and executing
code from the DSP internal RAMs, and this feature is enabled after
commit 1f1884de505c ("remoteproc/k3-dsp: Add support for L2RAM
loading on C66x DSPs"). These regions are currently mapped as
device type memory due to the usage of the devm_ioremap_resource()
function.

The remoteproc core ELF loader function zeroes out any remaining
portions of a program segment if the actual memory size (p_memsz)
is more than the loadable content (p_filesz), and this memset can
throw a kernel crash on these DSP internal memories. This is due
to the usage of the "DC ZVA" instruction within the Arm64 memset
library function when zeroing out memory, which throws an alignment
fault on device type memory.

So, update the mapping logic to instead use the devm_ioremap_wc()
function to map these memory regions as Normal Non-Cached memories,
and thereby fix the issues with memset().

An example crash log looks like below:
 remoteproc remoteproc0: phdr: type 1 da 0x800000 memsz 0x4a20 filesz 0x4a20
 remoteproc remoteproc0: phdr: type 1 da 0x804a20 memsz 0x378 filesz 0x0
 Unable to handle kernel paging request at virtual address ffff000012604a40
 Mem abort info:
   ESR = 0x96000061
   Exception class = DABT (current EL), IL = 32 bits
   SET = 0, FnV = 0
   EA = 0, S1PTW = 0
 Data abort info:
   ISV = 0, ISS = 0x00000061
   CM = 0, WnR = 1
 swapper pgtable: 64k pages, 48-bit VAs, pgdp = 00000000f098b163
 [ffff000012604a40] pgd=00000008fffe0003, pud=00000008fffe0003, pmd=00000008fffd0003, pte=00e8004d80800707
 Internal error: Oops: 96000061 [#1] PREEMPT SMP
 Modules linked in: ti_k3_dsp_remoteproc virtio_rpmsg_bus remoteproc
 Process kworker/1:0 (pid: 18, stack limit = 0x000000002b4c701b)
 CPU: 1 PID: 18 Comm: kworker/1:0 Not tainted 4.19.73-00004-g5de400066f93 #354
 Hardware name: Texas Instruments K3 J721E SoC (DT)
 Workqueue: events request_firmware_work_func
 pstate: 80000005 (Nzcv daif -PAN -UAO)
 pc : __memset+0x16c/0x188
 lr : rproc_elf_load_segments+0x100/0x1c8 [remoteproc]
 sp : ffff0000093afc80
 x29: ffff0000093afc80 x28: ffff80084178a838
 x27: 0000000000004a60 x26: 0000000000000378
 x25: ffff80084178a800 x24: ffff80084a6fca80
 x23: ffff000012b10000 x22: 0000000000804a20
 x21: 0000000000000000 x20: 0000000000000001
 x19: ffff000012fd65bc x18: 0000000000000087
 x17: 0000000000000000 x16: 0000000000000000
 x15: 0000000000000400 x14: 0000000000000400
 x13: 00000000000001ab x12: 0000000000000000
 x11: 0000000000000001 x10: 0000000000000980
 x9 : 0000000000000000 x8 : ffff000012604a40
 x7 : 0000000000000000 x6 : 000000000000003f
 x5 : 0000000000000040 x4 : ffffffffffffffe0
 x3 : 0000000000000358 x2 : 0000000000000318
 x1 : 0000000000000000 x0 : ffff000012604a20
 Call trace:
  __memset+0x16c/0x188
  rproc_boot+0x404/0x668 [remoteproc]
  rproc_auto_boot_callback+0x18/0x30 [remoteproc]
  request_firmware_work_func+0x48/0x88
  process_one_work+0x1e0/0x318
  worker_thread+0x40/0x428
  kthread+0x124/0x128
  ret_from_fork+0x10/0x18
 Code: 91010108 54ffff4a 8b040108 cb050042 (d50b7428)
 ---[ end trace eafd1b2b63d14eb0 ]---

Fixes: af9493dd36d4 ("remoteproc/k3-dsp: add a remoteproc driver of K3 C66x DSPs")
Signed-off-by: Suman Anna <s-anna@ti.com>
Suman Anna 6 年之前
父节点
当前提交
c9100d022c
共有 1 个文件被更改,包括 17 次插入3 次删除
  1. 17 3
      drivers/remoteproc/ti_k3_dsp_remoteproc.c

+ 17 - 3
drivers/remoteproc/ti_k3_dsp_remoteproc.c

@@ -6,6 +6,7 @@
  *	Suman Anna <s-anna@ti.com>
  */
 
+#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/of_reserved_mem.h>
@@ -482,10 +483,23 @@ static int k3_dsp_rproc_of_get_memories(struct platform_device *pdev,
 
 		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						   mem_names[i]);
-		kproc->mem[i].cpu_addr = devm_ioremap_resource(dev, res);
-		if (IS_ERR(kproc->mem[i].cpu_addr)) {
-			dev_err(dev, "failed to parse and map %s memory\n",
+		if (!res) {
+			dev_err(dev, "found no memory resource for %s\n",
+				mem_names[i]);
+			return -EINVAL;
+		}
+		if (!devm_request_mem_region(dev, res->start,
+					     resource_size(res),
+					     dev_name(dev))) {
+			dev_err(dev, "could not request %s region for resource\n",
 				mem_names[i]);
+			return -EBUSY;
+		}
+
+		kproc->mem[i].cpu_addr = devm_ioremap_wc(dev, res->start,
+							 resource_size(res));
+		if (IS_ERR(kproc->mem[i].cpu_addr)) {
+			dev_err(dev, "failed to map %s memory\n", mem_names[i]);
 			return PTR_ERR(kproc->mem[i].cpu_addr);
 		}
 		kproc->mem[i].bus_addr = res->start;