iomem
iomemはiomem_resourceをヘッド(領域)とする、struct resourceで管理されています。struct resourceはtree型の階層構造で、childは新規に管理する領域のオブジェクトとなります。
なお、新規管理領域はchildでリストされてきたobjectというのでなく、siblingで登録されているobjectでも、そのchildに登録されているbjectについても適用されます。
a->sibling = b; b->sibling = c; c->sibling = d; bはaの管理下。cはaの管理下。dはaの管理下。
a->sibling = b; b->child = c; c->sibling = d; bはaの管理下。cはbの管理下。dはcの管理下。
サンプルは/proc/iomemでオブジェくの名称と領域で、他の属性をも表示したものです。
iomem_resource領域は、0から-1で、/dev/memでの参照のチェックは結果的に全メモリ領域が対象となります。
なお、新規管理領域はchildでリストされてきたobjectというのでなく、siblingで登録されているobjectでも、そのchildに登録されているbjectについても適用されます。
struct resource { resource_size_t start; resource_size_t end; const char *name; unsigned long flags; struct resource *parent, *sibling, *child; }; struct resource iomem_resource = { .name = "PCI mem", .start = 0, .end = -1, .flags = IORESOURCE_MEM, };a->child = b; b->sibling = c; c->sibling = d; bはaの管理下。cはbの管理下。dはbの管理下。
a->sibling = b; b->sibling = c; c->sibling = d; bはaの管理下。cはaの管理下。dはaの管理下。
a->sibling = b; b->child = c; c->sibling = d; bはaの管理下。cはbの管理下。dはcの管理下。
サンプルは/proc/iomemでオブジェくの名称と領域で、他の属性をも表示したものです。
#include <linux/module.h> static struct resource *r_next(struct resource *p, int * attr); static char devmemattr[60]; char* devmem_ok(struct resource *p) { sprintf(devmemattr, "[BUSY:%d] [EXCLU:%d]", (p->flags & IORESOURCE_BUSY)? 1: 0, (p->flags & IORESOURCE_EXCLUSIVE)? 1: 0); return devmemattr; } static struct resource *r_next(struct resource *p, int *attr) { (*pos)++; *attr = 0; if (p->child) return p->child; while (!p->sibling && p->parent) p = p->parent; *attr = 1; return p->sibling; } static void r_get(struct resource *p) { int attr; char parent[64]; parent[0] = NULL; if (p->parent) { strcpy(parent, p->parent->name); } printk("%s:%08llx-%08llx : %30s: %30s %d.%d %s\n", (!attr)? "child ": "sible", (unsigned long long) p->start, (unsigned long long) p->end, p->name ? p->name : "<BAD>", parent, (p->child)? 1: 0, (p->sibling)? 1: 0, devmem_ok(p)); while ((p = r_next(p, &attr))) { parent[0] = NULL; if (p->parent) { strcpy(parent, p->parent->name); } printk("%s:%08llx-%08llx : %30s: %30s %d.%d %s\n", (!attr)? "child ": "sibling", (unsigned long long) p->start, (unsigned long long) p->end, p->name ? p->name : "<BAD>", parent, (p->child)? 1: 0, (p->sibling)? 1: 0, devmem_ok(p)); } } static int __init babakaka_init( void ) { r_get(&iomem_resource); return 1; } module_init(babakaka_init);結果
[root@localhost north]# insmod babakaka.ko [root@localhost north]# dmesg -c child :00000000-ffffffff : PCI mem: 1.0 [BUSY:0] [EXCLU:0] child :00000000-0000ffff : reserved: PCI mem 0.1 [BUSY:1] [EXCLU:0] sibling:00010000-0009f7ff : System RAM: PCI mem 0.1 [BUSY:1] [EXCLU:0] sibling:0009f800-0009ffff : reserved: PCI mem 0.1 [BUSY:1] [EXCLU:0] sibling:000a0000-000bffff : PCI Bus 0000:00: PCI mem 1.1 [BUSY:0] [EXCLU:0] child :000a0000-000bffff : Video RAM area: PCI Bus 0000:00 0.0 [BUSY:1] [EXCLU:0] sibling:000c0000-000c7fff : Video ROM: PCI mem 0.1 [BUSY:1] [EXCLU:0] sibling:000ca000-000cafff : Adapter ROM: PCI mem 0.1 [BUSY:1] [EXCLU:0] sibling:000cb000-000cbfff : Adapter ROM: PCI mem 0.1 [BUSY:1] [EXCLU:0] sibling:000cc000-000cffff : PCI Bus 0000:00: PCI mem 0.1 [BUSY:0] [EXCLU:0] sibling:000d0000-000d3fff : PCI Bus 0000:00: PCI mem 0.1 [BUSY:0] [EXCLU:0] sibling:000d4000-000d7fff : PCI Bus 0000:00: PCI mem 0.1 [BUSY:0] [EXCLU:0] sibling:000d8000-000dbfff : PCI Bus 0000:00: PCI mem 0.1 [BUSY:0] [EXCLU:0] sibling:000dc000-000fffff : reserved: PCI mem 1.1 [BUSY:1] [EXCLU:0] child :000f0000-000fffff : System ROM: reserved 0.0 [BUSY:1] [EXCLU:0] sibling:00100000-1feeffff : System RAM: PCI mem 1.1 [BUSY:1] [EXCLU:0] child :00400000-0093411e : Kernel code: System RAM 0.1 [BUSY:1] [EXCLU:0] sibling:0093411f-00bb6e3f : Kernel data: System RAM 0.1 [BUSY:1] [EXCLU:0] sibling:00c57000-00d4efff : Kernel bss: System RAM 0.0 [BUSY:1] [EXCLU:0] sibling:1fef0000-1fefefff : ACPI Tables: PCI mem 0.1 [BUSY:1] [EXCLU:0] sibling:1feff000-1fefffff : ACPI Non-volatile Storage: PCI mem 0.1 [BUSY:1] [EXCLU:0] sibling:1ff00000-1fffffff : System RAM: PCI mem 0.1 [BUSY:1] [EXCLU:0] sibling:20000000-febfffff : PCI Bus 0000:00: PCI mem 1.1 [BUSY:0] [EXCLU:0] child :20000000-20007fff : 0000:00:0f.0: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:20008000-2000bfff : 0000:00:10.0: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e5b00000-e5bfffff : PCI Bus 0000:22: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e5c00000-e5cfffff : PCI Bus 0000:1a: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e5d00000-e5dfffff : PCI Bus 0000:12: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e5e00000-e5efffff : PCI Bus 0000:0a: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e5f00000-e5ffffff : PCI Bus 0000:21: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e6000000-e60fffff : PCI Bus 0000:19: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e6100000-e61fffff : PCI Bus 0000:11: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e6200000-e62fffff : PCI Bus 0000:09: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e6300000-e63fffff : PCI Bus 0000:20: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e6400000-e64fffff : PCI Bus 0000:18: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e6500000-e65fffff : PCI Bus 0000:10: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e6600000-e66fffff : PCI Bus 0000:08: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e6700000-e67fffff : PCI Bus 0000:1f: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e6800000-e68fffff : PCI Bus 0000:17: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e6900000-e69fffff : PCI Bus 0000:0f: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e6a00000-e6afffff : PCI Bus 0000:07: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e6b00000-e6bfffff : PCI Bus 0000:1e: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e6c00000-e6cfffff : PCI Bus 0000:16: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e6d00000-e6dfffff : PCI Bus 0000:0e: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e6e00000-e6efffff : PCI Bus 0000:06: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e6f00000-e6ffffff : PCI Bus 0000:1d: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e7000000-e70fffff : PCI Bus 0000:15: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e7100000-e71fffff : PCI Bus 0000:0d: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e7200000-e72fffff : PCI Bus 0000:05: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e7300000-e73fffff : PCI Bus 0000:1c: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e7400000-e74fffff : PCI Bus 0000:14: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e7500000-e75fffff : PCI Bus 0000:0c: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e7600000-e76fffff : PCI Bus 0000:04: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e7700000-e77fffff : PCI Bus 0000:1b: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e7800000-e78fffff : PCI Bus 0000:13: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e7900000-e79fffff : PCI Bus 0000:0b: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e7a00000-e7afffff : PCI Bus 0000:03: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:e7b00000-e7ffffff : PCI Bus 0000:02: PCI Bus 0000:00 1.1 [BUSY:0] [EXCLU:0] child :e7b00000-e7b0ffff : 0000:02:01.0: PCI Bus 0000:02 0.1 [BUSY:0] [EXCLU:0] sibling:e7b10000-e7b1ffff : 0000:02:05.0: PCI Bus 0000:02 0.0 [BUSY:0] [EXCLU:0] sibling:e8000000-efffffff : 0000:00:0f.0: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:f0000000-f7ffffff : PCI MMCONFIG 0000 [bus 00-7f]: PCI Bus 0000:00 1.1 [BUSY:1] [EXCLU:0] child :f0000000-f7ffffff : reserved: PCI MMCONFIG 0000 [bus 00-7f] 1.0 [BUSY:0] [EXCLU:0] child :f0000000-f7ffffff : pnp 00:0d: reserved 0.0 [BUSY:0] [EXCLU:0] sibling:fb500000-fb5fffff : PCI Bus 0000:22: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fb600000-fb6fffff : PCI Bus 0000:1a: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fb700000-fb7fffff : PCI Bus 0000:12: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fb800000-fb8fffff : PCI Bus 0000:0a: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fb900000-fb9fffff : PCI Bus 0000:21: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fba00000-fbafffff : PCI Bus 0000:19: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fbb00000-fbbfffff : PCI Bus 0000:11: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fbc00000-fbcfffff : PCI Bus 0000:09: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fbd00000-fbdfffff : PCI Bus 0000:20: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fbe00000-fbefffff : PCI Bus 0000:18: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fbf00000-fbffffff : PCI Bus 0000:10: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fc000000-fc0fffff : PCI Bus 0000:08: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fc100000-fc1fffff : PCI Bus 0000:1f: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fc200000-fc2fffff : PCI Bus 0000:17: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fc300000-fc3fffff : PCI Bus 0000:0f: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fc400000-fc4fffff : PCI Bus 0000:07: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fc500000-fc5fffff : PCI Bus 0000:1e: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fc600000-fc6fffff : PCI Bus 0000:16: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fc700000-fc7fffff : PCI Bus 0000:0e: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fc800000-fc8fffff : PCI Bus 0000:06: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fc900000-fc9fffff : PCI Bus 0000:1d: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fca00000-fcafffff : PCI Bus 0000:15: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fcb00000-fcbfffff : PCI Bus 0000:0d: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fcc00000-fccfffff : PCI Bus 0000:05: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fcd00000-fcdfffff : PCI Bus 0000:1c: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fce00000-fcefffff : PCI Bus 0000:14: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fcf00000-fcffffff : PCI Bus 0000:0c: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fd000000-fd0fffff : PCI Bus 0000:04: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fd100000-fd1fffff : PCI Bus 0000:1b: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fd200000-fd2fffff : PCI Bus 0000:13: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fd300000-fd3fffff : PCI Bus 0000:0b: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fd400000-fd4fffff : PCI Bus 0000:03: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fd500000-fdffffff : PCI Bus 0000:02: PCI Bus 0000:00 1.1 [BUSY:0] [EXCLU:0] child :fd5ff000-fd5fffff : 0000:02:02.0: PCI Bus 0000:02 1.0 [BUSY:0] [EXCLU:0] child :fd5ff000-fd5fffff : ehci_hcd: 0000:02:02.0 0.0 [BUSY:1] [EXCLU:0] sibling:fe000000-fe7fffff : 0000:00:0f.0: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:fe800000-fe9fffff : pnp 00:0d: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:febfd000-febfd01f : 0000:00:10.0: PCI Bus 0000:00 0.1 [BUSY:0] [EXCLU:0] sibling:febfe000-febfffff : 0000:00:07.7: PCI Bus 0000:00 0.0 [BUSY:0] [EXCLU:0] sibling:fec00000-fec0ffff : reserved: PCI mem 1.1 [BUSY:0] [EXCLU:0] child :fec00000-fec003ff : IOAPIC 0: reserved 0.0 [BUSY:1] [EXCLU:0] sibling:fed00000-fed003ff : HPET 0: PCI mem 1.1 [BUSY:0] [EXCLU:0] child :fed00000-fed003ff : pnp 00:08: HPET 0 0.0 [BUSY:0] [EXCLU:0] sibling:fee00000-fee00fff : Local APIC: PCI mem 1.1 [BUSY:1] [EXCLU:0] child :fee00000-fee00fff : reserved: Local APIC 0.0 [BUSY:0] [EXCLU:0] sibling:fffe0000-ffffffff : reserved: PCI mem 0.0 [BUSY:0] [EXCLU:0]
追記
/dev/memのread/writeコールバックは、参照可能かのチェックにiomem_is_exclusive()がコールし、参照領域がiomem領域でIORESOURCE_BUSY/IORESOURCE_EXCLUSIVEなら参照できません。デバイスドライバで、IORESOURCE_EXCLUSIVEをflagにセットして、登録すればドライバが参照中に/dev/memで参照させなくできます。iomem_resource領域は、0から-1で、/dev/memでの参照のチェックは結果的に全メモリ領域が対象となります。
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)) { if (p->start >= addr + size) break; if (p->end < addr) continue; if (p->flags & IORESOURCE_BUSY && p->flags & IORESOURCE_EXCLUSIVE) { err = 1; break; } } read_unlock(&resource_lock); return err; }