Crash while iterating over devices and resource

Martin dragonfly at wommm.nl
Thu May 3 14:50:23 PDT 2007


Hi all,

Since the old ndisulator code (which is in DragonFly) doesn't recognize 
my wireless card I've taken a shot at converting the current ndisulator 
code of FreeBSD to DragonFly.

The code now correctly identifies my wireless card however the 
win-driver want to map io space. In the function where ndisulator does 
this it recursively iterate over all devices and resources to select the 
correct device to map to. The driver crashes in this code.

Attached is a minimal example of the code which crashes (it crashes in 
the SLIST_FOREACH [macro]call) and a dump of the output just prior to 
crashing and after the crash.

Since I don't now much about hardware I'm not sure whether it is normal 
that pci1 is a child of pci0, and I also would have thought the 
resource_list pointer of pci1 (which it crashes on) would be more in 
sequentual to the pointer of the resource_list pointers of agp0 and pcib1.

Hope one of you can help.

Martin
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/malloc.h>

#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/conf.h>

#include <sys/bus.h>
#include <sys/rman.h>

static void
print_spaces(int len)
{
	int		i;

	for (i = 0; i < len; i++) {
		kprintf(" ");
	}
}

static void
walk_tree(device_t dev, int depth)
{
	int 				i;
	struct resource			*r;
	struct resource_list		*rl;
	struct resource_list_entry	*rle;
	device_t			*children;
	int				child_cnt;

	print_spaces(depth * 2);
	device_print_prettyname(dev);
	kprintf(" %sactive", (device_is_alive(dev) == FALSE ? "in" : ""));

	rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);

	kprintf(" (resource head: %p)\n", rl);
	if (rl != NULL) {
		SLIST_FOREACH(rle, rl, link) {
			r = rle->res;
			print_spaces(depth * 2 + 2);
			kprintf("resource: type = %x, start = %X, end = %X\n",
			    rle->type, rman_get_start(r), rman_get_end(r));
		}
	}

	device_get_children(dev, &children, &child_cnt);
	for (i = 0; i < child_cnt; i++) {
		walk_tree(children[i], depth + 1);
	}
	kfree(children, M_TEMP);
}

static int
res_modevent(module_t mod, int cmd, void *arg)
{
	int			i;
	int			error = 0;
	devclass_t		nexus_class;
	device_t		*nexus_devs;
	int			nexus_cnt = 0;;

	switch (cmd) {
	case MOD_LOAD:
		nexus_class = devclass_find("nexus");
		devclass_get_devices(nexus_class, &nexus_devs, &nexus_cnt);
		for (i = 0; i < nexus_cnt; i++) {
			walk_tree(nexus_devs[i], 0);
		}

		kfree(nexus_devs, M_TEMP);

		error = EINVAL;
		break;
	case MOD_SHUTDOWN:
		break;
	case MOD_UNLOAD:
		break;
	default:
		error = EINVAL;
		break;
	}

	return(error);
}

DEV_MODULE(resources, res_modevent, NULL);
MODULE_VERSION(resources, 1);

Unread portion of the kernel message buffer:
nexus0:  active (resource head: 0)
  apm0:  inactive (resource head: 0)
  npx0:  active (resource head: 0)
  acpi0:  active (resource head: 0)
    acpi_timer0:  active (resource head: 0)
    cpu0:  active (resource head: 0)
    unknown:  inactive (resource head: 0)
    acpi_tz0:  active (resource head: 0)
    acpi_button0:  active (resource head: 0)
    acpi_button1:  active (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    acpi_sysresource0:  active (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
    unknown:  inactive (resource head: 0)
  eisa0:  inactive (resource head: 0)
  legacypci0:  active (resource head: 0)
    pcib0:  active (resource head: 0)
      pci0:  active (resource head: 0)
        agp0:  active (resource head: 0xc0d061d4)
          resource: type = 3, start = E0000000, end = E3FFFFFF
        pcib1:  active (resource head: 0xc0d06234)
          pci1:  active (resource head: 0x4)


Fatal trap 12: page fault while in kernel mode
fault virtual address	= 0x4
fault code		= supervisor read, page not present
instruction pointer	= 0x8:0xcc796616
stack pointer	        = 0x10:0xcc76aae4
frame pointer	        = 0x10:0xcc76ab08
code segment		= base 0x0, limit 0xfffff, type 0x1b
			= DPL 0, pres 1, def32 1, gran 1
processor eflags	= interrupt enabled, resume, IOPL = 0
current process		= 691 (kldload)
current thread          = pri 10 

panic: from debugger


Fatal trap 3: breakpoint instruction fault while in kernel mode
instruction pointer	= 0x8:0xc04f5089
stack pointer	        = 0x10:0xcc76a8a0
frame pointer	        = 0x10:0xcc76a8a8
code segment		= base 0x0, limit 0xfffff, type 0x1b
			= DPL 0, pres 1, def32 1, gran 1
processor eflags	= interrupt enabled, IOPL = 0
current process		= 691 (kldload)
current thread          = pri 10 

panic: from debugger
Uptime: 1m46s

dumping to dev #ad/0x20009, offset 1835008
dump 128 127 126 125 124 123 122 121 120 119 118 117 116 115 114 113 112 111 110 109 108 107 106 105 104 103 102 101 100 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 

GNU gdb 6.2.1
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-dragonfly".
(kgdb) quit




More information about the Kernel mailing list