Dtrace oddity

Christopher Bowman crb at chrisbowman.com
Tue Apr 11 07:17:02 UTC 2017


Apologies if I’m sending to the wrong list.  I have a small test program shown at the bottom.  It tries to mmap a device for which I’ve written (a possibly incorrect) driver.  When I run the program I get the following output:   

crb at retread:63> ./test /dev/sp6050 
argc = 2
argv[0] = ./test
argv[1] = /dev/sp6050
opening device /dev/sp6050
open returned non-zero value
mmap failed: EINVAL

The man page lists a bunch of reasons for EINVAL so I want to investigate this and I don’t quite know good strategies to debug the kernel (yet) so I thought I’d experiment with Dtrace a bit.  Here is the oddity: when I run Dtrace and then run my test program I get the following output from Dtrace:

crb at retread:60> dtrace -n 'syscall:freebsd:mmap:entry /execname == "test"/ {}'
dtrace: description 'syscall:freebsd:mmap:entry ' matched 1 probe
CPU     ID                    FUNCTION:NAME
  0  63401                       mmap:entry 
  0  63401                       mmap:entry 
  0  63401                       mmap:entry 
  0  63401                       mmap:entry 
  0  63401                       mmap:entry 
  0  63401                       mmap:entry 
  0  63401                       mmap:entry 
  0  63401                       mmap:entry 
  0  63401                       mmap:entry 
  0  63401                       mmap:entry 
  0  63401                       mmap:entry 
  0  63401                       mmap:entry 

I think Dtrace is indicating that the mmap syscall was called 12 times by my test program yet I can see how the program below would have done that.

Here is my program:

/*
	Copyright (c) 2011 by Christopher R. Bowman. All rights reserved.
*/

#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>


int main (int argc, char ** argv) {
	int i;

	printf("argc = %d\n", argc);
	for (i=0; i < argc; i++)
		printf ("argv[%i] = %s\n", i, argv[i]);
	if (argc < 2) {
		printf("usage: test device\n");
		return 0;
	}
	printf("opening device %s\n", argv[1]);
	int device = open (argv[1], O_RDWR);
	if (device == 0) {
		printf ("open of device %s failed\n", argv[1]);
		return 0;
	}
	printf("open returned non-zero value\n");
	void *pa = mmap (0, 4095, PROT_READ | PROT_WRITE, 0, device, 0);
	if (pa == MAP_FAILED) {
		printf ("mmap failed: ");
		switch (errno) {
			case EACCES: printf("EACCESS\n"); break;
			case EBADF:  printf("EBADF\n"); break;
			case EINVAL: printf("EINVAL\n"); break;
			case ENODEV: printf("ENODEV\n"); break;
			case ENOMEM: printf("ENOMEM\n"); break;
		}
		return 0;
	}
	printf("mmap returned non-zero value: %lx\n", (unsigned long)pa);
	unsigned int *p = (unsigned int *) pa;
	unsigned char *c = (unsigned char *) pa;
#define NUM_ITERATIONS 16
	for (i=0; i < NUM_ITERATIONS; i++){	//BARs are 2Kbytes
		//*p++ = (0xa5a5 + i);
		*p++ = (0x5aa5a5a5);
	}
	p = (unsigned int *) pa;
	for (i=0; i < NUM_ITERATIONS; i++){
		printf("i = %d, read_val = %x\n", i, *p++);
	}
}


Thanks in advance for comments on Dtrace or perhaps program corrections or ideas why the mmap failed or places to read on kernel debugging or pointers to a better list to which to send this.
Thanks
Christopher




More information about the freebsd-hackers mailing list