设备树reserved-memory的no-map属性疑问:为何可通过虚拟地址访问
问题:reserved-memory的no-map属性为何未阻止驱动创建虚拟映射?
设备树配置
reserved-memory { #address-cells = <2>; #size-cells = <2>; ranges; axpu_reserved_mem: axpursvd@90000000 { no-map; reg = <0x0 0x90000000 0x0 0x30000000>; }; }; axpu@50000000 { compatible = "ab21-axpu"; reg = <0 0x50000000 0 0x10000000>; ... memory-region = <&axpu_reserved_mem>; };
驱动关键代码
probe函数(简化版)
struct axpu_dev { struct device *dev; void __iomem *base; u64 paddr; u64 vaddr; }; static int axpu_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct resource *res; struct axpu_dev *axpu; struct device_node *np; int rc; int ret; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); axpu = devm_kzalloc(dev, sizeof(*axpu), GFP_KERNEL); axpu->dev = dev; axpu->base = devm_ioremap(dev, res->start, resource_size(res)); res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); devm_request_irq(dev, res->start, axpu_irq_handler, IRQF_TRIGGER_HIGH, "axpu_irq", axpu); np = of_parse_phandle(dev->of_node, "memory-region", 0); rc = of_address_to_resource(np, 0, res); axpu->paddr = res->start; axpu->vaddr = memremap(res->start, resource_size(res), MEMREMAP_WB); platform_set_drvdata(pdev, axpu); axpu_init(axpu); return sysfs_create_group(&dev->kobj, &axpu_attr_group); }
axpu_init函数
static void axpu_init(struct axpu_dev *axpu) { printk("testing reserved memory ..\n"); writel_relaxed(0x12345678, axpu->vaddr + 0); writel_relaxed(0x23456789, axpu->vaddr + 8); printk("read-back data = %llx, %llx\n", readl_relaxed(axpu->vaddr + 0), readl_relaxed(axpu->vaddr + 8)); }
运行现象
正常访问日志
/ # insmod axpu.ko axpu_probe called! MEM : res->start = 50000000, res->end = 5fffffff, res->name = axpu@50000000 axpu->base = ffffffc010000000 IRQ : res->start = 15, res->end = 15, res->name = axpu@50000000 axpu_dev 50000000.axpu: Allocated reserved memory, vaddr: 0xFFFFFFC080000000, paddr: 0x90000000 writing 0x12345678 at non-mapped reserved memory 0x90000000, 0x90000008 .. read-back data = 12345678, 23456789
直接访问物理地址崩溃日志
------------[ cut here ]------------ Ignoring spurious kernel translation fault at virtual address 0000000090000000 WARNING: CPU: 0 PID: 27 at arch/arm64/mm/fault.c:311 __do_kernel_fault+0x108/0x150 odules linked in: axpu(+) CPU: 0 PID: 27 Comm: insmod Not tainted 5.10.0-rc5 #548 Hardware name: ETRI ab21m (DT) pstate: 60400009 (nZCv daif +PAN -UAO -TCO BTYPE=--) pc : __do_kernel_fault+0x108/0x150 lr : __do_kernel_fault+0x108/0x150
问题分析与解答
你的设备树配置没有问题,no-map的行为完全符合设计预期:
no-map的核心作用是禁止内核为该预留内存创建全局线性映射(即内核虚拟地址空间中直接映射物理地址的默认区域),而非禁止驱动通过手动映射函数创建映射。- 直接访问物理地址0x90000000崩溃,恰恰证明这段内存没有被加入内核的全局线性映射,完全符合
no-map的要求。 - 驱动中通过
memremap()手动创建虚拟映射是被允许的,这正是no-map设计的初衷——将内存映射的控制权完全交给驱动,而非由内核自动管理。
如果需要让这段内存完全无法被任何方式映射(极端场景),需要额外的硬件或内核配置,但常规场景下,你的当前配置和行为都是正常的。
内容的提问来源于stack exchange,提问作者Chan Kim
相关产品推荐
相关产品推荐

