Код: Выделить всё
.
.
.
reserved-memory {
#address-cells = ;
#size-cells = ;
ranges;
/* Reserved memory for COM.2 firmware */
reserved: memory@8000000 {
no-map;
reg = ;
};
};
xlnx-com2@8000000 {
compatible = "xlnx,reserved-memory";
memory-region = ;
};
};
};
};
Это мой код:
Код: Выделить всё
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DRV_NAME "com2"
static char *fpgaupdate;
module_param(fpgaupdate, charp, 0444);
static int com2_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np;
struct resource res;
phys_addr_t mem_paddr;
void __iomem *mem_vaddr;
size_t mem_size;
int ret = 0;
const struct firmware *fw;
size_t offset = 0;
size_t chunk_size;
if (fpgaupdate == NULL) {
dev_err(dev, "fpgaupdate parameter is missing\n");
return -EINVAL;
}
ret = request_firmware(&fw, fpgaupdate, dev);
if (ret) {
dev_err(dev, "failed to request firmware. error: %d\n", ret);
return ret;
}
dev_info(dev, "firmware size: %ld bytes\n", fw->size);
np = of_parse_phandle(dev->of_node, "memory-region", 0);
if (!np) {
dev_err(dev, "No %s specified\n", "memory-region");
ret = -EINVAL;
goto rel_fw;
}
ret = of_address_to_resource(np, 0, &res);
if (ret) {
dev_err(dev, "No memory address assigned to the region\n");
goto rel_fw;
}
mem_paddr = res.start;
mem_size = resource_size(&res);
if (fw->size > mem_size) {
dev_err(dev, "firmware size exceeds reserved memory size\n");
ret = -ENOMEM;
goto rel_fw;
}
while (offset < fw->size) {
dev_info(dev, "fw_size 0x%lx, offset 0x%lx\n", fw->size, offset);
chunk_size = min((size_t)PAGE_SIZE, fw->size - offset);
// if (!IS_ALIGNED(mem_paddr + offset, PAGE_SIZE)) {
// dev_err(dev, "Memory access is not page aligned!\n");
// ret = -EINVAL;
// goto rel_fw;
// }
mem_vaddr = memremap(mem_paddr + offset, chunk_size, MEMREMAP_WB);
if (!mem_vaddr) {
dev_err(dev, "failed to remap reserved memory region\n");
ret = -ENOMEM;
goto rel_fw;
}
dev_info(dev, "vaddr received 0x%p, \n", mem_vaddr);
memcpy_toio(mem_vaddr, fw->data + offset, chunk_size);
dev_info(dev, "Copied %ld bytes to reserved memory at offset 0x%lx\n", chunk_size, offset);
memunmap(mem_vaddr);
offset += chunk_size;
}
rel_fw:
release_firmware(fw);
return ret;
}
static int com2_remove(struct platform_device *pdev)
{
dev_info(&pdev->dev, "firmware loader module removed\n");
return 0;
}
static const struct of_device_id com2_of_match[] = {
{ .compatible = "xlnx,reserved-memory", },
{},
};
MODULE_DEVICE_TABLE(of, com2_of_match);
static struct platform_driver com2_driver = {
.probe = com2_probe,
.remove = com2_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = com2_of_match,
},
};
module_platform_driver(com2_driver);
MODULE_ALIAS("platform:" DRV_NAME);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("com2 driver");
В идеале я хотел бы сопоставить весь регион один раз. а затем просто скопируйте полный битовый поток прошивки в область памяти, но во время memcpy() происходит сбой ядра. Вот почему я копирую данные частями по 4 КБ, чтобы сузить источник ошибки.
После успешного копирования некоторых фрагментов данных внезапно происходит сбой. Заметил, что не всегда крашится по одному и тому же физическому адресу. Иногда перед сбоем копируется 1/3 данных, а иногда всего несколько Кбайт.
Это вывод ошибки:
Код: Выделить всё
[ 127.396751] com2 xlnx-com2@8000000: firmware size: 3652740 bytes
[ 127.396801] com2 xlnx-com2@8000000: fw_size 0x37bc84, offset 0x0
[ 127.396819] com2 xlnx-com2@8000000: vaddr received 0x00000000e1ff176d,
[ 127.396831] com2 xlnx-com2@8000000: Copied 4096 bytes to reserved memory at offset 0x0
[ 127.396837] com2 xlnx-com2@8000000: fw_size 0x37bc84, offset 0x1000
[ 127.396844] com2 xlnx-com2@8000000: vaddr received 0x000000003e2c1ae9,
[ 127.396854] com2 xlnx-com2@8000000: Copied 4096 bytes to reserved memory at offset 0x1000
[ 127.396860] com2 xlnx-com2@8000000: fw_size 0x37bc84, offset 0x2000
[ 127.396866] com2 xlnx-com2@8000000: vaddr received 0x00000000edb34175,
[ 127.396876] com2 xlnx-com2@8000000: Copied 4096 bytes to reserved memory at offset 0x2000
[ 127.396957] com2 xlnx-com2@8000000: fw_size 0x37bc84, offset 0x3000
.
.
(I removed some printlogs here to shorten the output...)
.
.
[ 127.400867] com2 xlnx-com2@8000000: fw_size 0x37bc84, offset 0xbe000
[ 127.400873] com2 xlnx-com2@8000000: vaddr received 0x00000000a7c0dd17,
[ 127.400881] com2 xlnx-com2@8000000: Copied 4096 bytes to reserved memory at offset 0xbe000
[ 127.400887] com2 xlnx-com2@8000000: fw_size 0x37bc84, offset 0xbf000
[ 127.400893] com2 xlnx-com2@8000000: vaddr received 0x00000000c459ba52,
[ 127.400901] com2 xlnx-com2@8000000: Copied 4096 bytes to reserved memory at offset 0xbf000
[ 127.400906] com2 xlnx-com2@8000000: fw_size 0x37bc84, offset 0xc0000
[ 127.400913] com2 xlnx-com2@8000000: vaddr received 0x000000001477362a,
[ 127.400921] com2 xlnx-com2@8000000: Copied 4096 bytes to reserved memory at offset 0xc0000
[ 127.400927] com2 xlnx-com2@8000000: fw_size 0x37bc84, offset 0xc1000
[ 127.400941] Unable to handle kernel paging request at virtual address 30a1001cb9f45354
[ 127.409371] Mem abort info:
[ 127.412169] ESR = 0x0000000096000004
[ 127.415917] EC = 0x25: DABT (current EL), IL = 32 bits
[ 127.421234] SET = 0, FnV = 0
[ 127.424283] EA = 0, S1PTW = 0
[ 127.427420] FSC = 0x04: level 0 translation fault
[ 127.432296] Data abort info:
[ 127.435167] ISV = 0, ISS = 0x00000004
[ 127.439000] CM = 0, WnR = 0
[ 127.441965] [30a1001cb9f45354] address between user and kernel address ranges
[ 127.449109] Internal error: Oops: 0000000096000004 [#1] PREEMPT_RT SMP
[ 127.449117] Modules linked in: com2(OE+) - XXXXXXXX
[ 127.449187] CPU: 2 PID: 1192 Comm: insmod Tainted: G OE 6.1.33-rt11-31 #1
[ 127.449195] Hardware name: XXXXXXXXXX
[ 127.449199] pstate: 80000005 (Nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 127.449206] pc : region_intersects+0x78/0xf8
[ 127.449221] lr : region_intersects+0x40/0xf8
[ 127.449229] sp : ffffff800839b820
[ 127.449231] x29: ffffff800839b820 x28: ffffff80080c0000 x27: 0000000000001000
[ 127.449241] x26: 0000000008000000 x25: ffffffc000a0c118 x24: ffffffc000a0c160
[ 127.449249] x23: 0000000001000200 x22: 0000000000000000 x21: 00000000080c1000
[ 127.449258] x20: ffffffc008fd1090 x19: 0000000000000000 x18: 0000000000000020
[ 127.449267] x17: 000058d800005ce8 x16: 000061300000d160 x15: ffffff8004e93c90
[ 127.449275] x14: 0000000000000000 x13: ffffffc009154542 x12: ffffffc00915453b
[ 127.449284] x11: 6d656d2064657672 x10: 000000000000000a x9 : ffffffc0089dd534
[ 127.449293] x8 : 000000000000000a x7 : 000000000000000f x6 : 00000000fffff40b
[ 127.449301] x5 : ffffff807fe6c8d8 x4 : 30a1001cb9f4533c x3 : 30a0000330e00017
[ 127.449310] x2 : 10d6000011130000 x1 : 00000000080c1fff x0 : 0000000000000001
[ 127.449319] Call trace:
[ 127.449321] region_intersects+0x78/0xf8
[ 127.449331] memremap+0x38/0x238
[ 127.449341] com2_probe+0x1bc/0x25c [com2]
[ 127.449359] platform_probe+0x70/0xe0
[ 127.449368] really_probe+0xc4/0x2b0
[ 127.449374] __driver_probe_device+0x80/0x120
[ 127.449380] driver_probe_device+0x44/0x120
[ 127.449385] __driver_attach+0x7c/0x130
[ 127.449391] bus_for_each_dev+0x78/0xd0
[ 127.449401] driver_attach+0x2c/0x38
[ 127.449410] bus_add_driver+0x15c/0x210
[ 127.449418] driver_register+0x6c/0x128
[ 127.449424] __platform_driver_register+0x30/0x40
[ 127.449431] com2_driver_init+0x28/0x1000 [com2]
[ 127.449445] do_one_initcall+0x50/0x2e0
[ 127.449453] do_init_module+0x50/0x1f8
[ 127.449462] load_module+0x1828/0x1d50
[ 127.449470] __do_sys_finit_module+0xc0/0x118
[ 127.449478] __arm64_sys_finit_module+0x28/0x38
[ 127.449485] invoke_syscall+0x4c/0x110
[ 127.449494] el0_svc_common.constprop.0+0x4c/0xf8
[ 127.449501] do_el0_svc+0x24/0x30
[ 127.449509] el0_svc+0x20/0x60
[ 127.449518] el0t_64_sync_handler+0xb8/0xc0
[ 127.449526] el0t_64_sync+0x174/0x178
[ 127.449536] Code: eb0202bf 1a938673 f9401884 b4000224 (f9400c83)
Будем очень благодарны за любую помощь или подсказку. Спасибо!
Я следовал документации xilinx по зарезервированной памяти: https://xilinx-wiki.atlassian.net/wiki/ ... d+Memory.Я также пытался удалить no-map, так что посмотрите, повлияет ли это... но я все равно получаю ту же ошибку.
Подробнее здесь: https://stackoverflow.com/questions/790 ... via-module