CONFIG_STRICT_DEVMEM和CONFIG_IO_STRICT_DEVMEM 和dev/mem的关系.
首先会影响dev/mem中映射memory更严格的检测,具体flow如下:
#ifdef CONFIG_STRICT_DEVMEM
static inline int range_is_allowed(unsigned long pfn, unsigned long size)
{
u64 from = ((u64)pfn) << PAGE_SHIFT;
u64 to = from + size;
u64 cursor = from;
while (cursor < to) {
if (!devmem_is_allowed(pfn))
return 0;
cursor += PAGE_SIZE;
pfn++;
}
return 1;
}
#else
static inline int range_is_allowed(unsigned long pfn, unsigned long size)
{
return 1;
}
#endif
可以看到对mem.c的影响就是range_is_allowed不在直接返回1了,而是调用range_is_allowed 来做检测
#ifdef CONFIG_STRICT_DEVMEM
#include <linux/ioport.h>
/*
* devmem_is_allowed() checks to see if /dev/mem access to a certain address
* is valid. The argument is a physical page number. We mimic x86 here by
* disallowing access to system RAM as well as device-exclusive MMIO regions.
* This effectively disable read()/write() on /dev/mem.
*/
int devmem_is_allowed(unsigned long pfn)
{
if (iomem_is_exclusive(pfn << PAGE_SHIFT))
return 0;
if (!page_is_ram(pfn))
return 1;
return 0;
}
devmem_is_allowed的检测有分成两部分iomem_is_exclusive 和 page_is_ram
#ifdef CONFIG_STRICT_DEVMEM
static int strict_iomem_checks = 1;
#else
static int strict_iomem_checks;
#endif
/*
* check if an address is reserved in the iomem resource tree
* returns 1 if reserved, 0 if not reserved.
*/
int iomem_is_exclusive(u64 addr)
{
struct resource *p = &iomem_resource;
int err = 0;
loff_t l;
int size = PAGE_SIZE;
if (!strict_iomem_checks)
return 0;
addr = addr & PAGE_MASK;
read_lock(&resource_lock);
for (p = p->child; p ; p = r_next(NULL, p, &l)) {
/*
* We can probably skip the resources without
* IORESOURCE_IO attribute?
*/
if (p->start >= addr + size)
break;
if (p->end < addr)
continue;
/*
* A resource is exclusive if IORESOURCE_EXCLUSIVE is set
* or CONFIG_IO_STRICT_DEVMEM is enabled and the
* resource is busy.
*/
if ((p->flags & IORESOURCE_BUSY) == 0)
continue;
if (IS_ENABLED(CONFIG_IO_STRICT_DEVMEM)
|| p->flags & IORESOURCE_EXCLUSIVE) {
err = 1;
break;
}
}
read_unlock(&resource_lock);
return err;
}
static int __init strict_iomem(char *str)
{
if (strstr(str, "relaxed"))
strict_iomem_checks = 0;
if (strstr(str, "strict"))
strict_iomem_checks = 1;
return 1;
}
__setup("iomem=", strict_iomem);
/*
* This generic page_is_ram() returns true if specified address is
* registered as System RAM in iomem_resource list.
*/
int __weak page_is_ram(unsigned long pfn)
{
return walk_system_ram_range(pfn, 1, NULL, __is_ram) == 1;
}
EXPORT_SYMBOL_GPL(page_is_ram);
因此即使开了CONFIG_STRICT_DEVMEM和CONFIG_IO_STRICT_DEVMEM,也可以在bootloader中传递iomem=relaxed,这样就会在iomem_is_exclusive 函数的前面返回,不做严格检测.
int iomem_is_exclusive(u64 addr)
{
struct resource *p = &iomem_resource;
int err = 0;
loff_t l;
int size = PAGE_SIZE;
if (!strict_iomem_checks)
return 0;
}