Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 12 Jan 2001 16:29:29 -0800
From:      Jeff Roberson <jeff@midstream.com>
To:        'Bruce Evans' <bde@zeta.org.au>
Cc:        "'freebsd-current@freebsd.org'" <freebsd-current@freebsd.org>
Subject:   RE: Broken mmap in current?
Message-ID:  <31E4B6337A4FD411BD45000102472E0C05E72A@EMAIL_SERVER>

index | next in thread | raw e-mail

[-- Attachment #1 --]
I think I spoke too soon..  I saw thousands of calls to mmap and assumed it
was the thousands of read/writes that I was doing.  It's actually for the
thousands (8192) of pages that I'm mapping in.  Oddly enough though there
are only 3272 calls to my mmap routine each time I run the program.  I will
investigate further.

I did find a bug in mlock() and munlock().  I tried mlock()ing after I
mmaped, which I later realized was bogus since the pages are always resident
as they exist on the bus.  Anyway the kernel faults in vm_page_unwire when I
munlock.  I will investigate further and post a pr though.

Thanks for your help!
Jeff

-----Original Message-----
From: Bruce Evans [mailto:bde@zeta.org.au]
Sent: Thursday, January 11, 2001 8:52 PM
To: Jeff Roberson
Cc: 'freebsd-current@freebsd.org'
Subject: Re: Broken mmap in current?


On Thu, 11 Jan 2001, Jeff Roberson wrote:

> I have written a character device driver for a proprietary PCI device that
> has a large sum of mapable memory.  The character device supports mmap()
> which I use to export the memory into a user process.  I have no problems
> accessing the memory on this device, but I notice that my mmap routine is
> called for every access!  Is this a problem with current, or a problem
with
> my mmap?

Maybe both.  The device mmap routine is called mainly by the mmap
syscall for every page to be mmapped.  It is also called by
dev_pager_getpages() for some pagefaults, but I think this rarely happens.

> I use bus_alloc_resource and then rman_get_start to get the physical
address
> in my attach, and then the mmap just returns atop(physical address).  I
> assumed this is correct since I have verified with a logical analyzer that
I
> am indeed writing to the memory on the device.

This is correct.  I looked at some examples.  Many drivers get this
wrong by using i386_btop(), alpha_btop(), etc.  (AFAIK, atop() is
for addresses which are what we are converting here, btop() is for
(byte) offsets, and the machine-dependent prefixes are a vestige of
page clustering code that mostly went away 7 years ago.

> Also, I noticed that the
> device's mmap interface does not provide any way to limit the size of the
> block being mapped?  Can I specify the length of the region?

The length is implicitly PAGE_SIZE.  The device mmap function is called
for each page to be mapped.  It must verify that the memory from offset
to (offset + PAGE_SIZE - 1) belongs to the device and can be accessed
with the given protection, and do any device-specific things necessary to
enable this memory.  This scheme can't support bank-switched device
memory very well, if at all.

pcvvt_mmap() in the pcvt driver is the simplest example of this.
agp_mmap() is a more up to date example with the same old bug that the
vga drivers used to have (off by 1 (page) error checking the offset).

Bruce



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message

[-- Attachment #2 --]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Generator" CONTENT="MS Exchange Server version 5.5.2650.12">
<TITLE>RE: Broken mmap in current?</TITLE>
</HEAD>
<BODY>

<P><FONT SIZE=2>I think I spoke too soon..&nbsp; I saw thousands of calls to mmap and assumed it was the thousands of read/writes that I was doing.&nbsp; It's actually for the thousands (8192) of pages that I'm mapping in.&nbsp; Oddly enough though there are only 3272 calls to my mmap routine each time I run the program.&nbsp; I will investigate further.</FONT></P>

<P><FONT SIZE=2>I did find a bug in mlock() and munlock().&nbsp; I tried mlock()ing after I mmaped, which I later realized was bogus since the pages are always resident as they exist on the bus.&nbsp; Anyway the kernel faults in vm_page_unwire when I munlock.&nbsp; I will investigate further and post a pr though.</FONT></P>

<P><FONT SIZE=2>Thanks for your help!</FONT>
<BR><FONT SIZE=2>Jeff</FONT>
</P>

<P><FONT SIZE=2>-----Original Message-----</FONT>
<BR><FONT SIZE=2>From: Bruce Evans [<A HREF="mailto:bde@zeta.org.au">mailto:bde@zeta.org.au</A>]</FONT>
<BR><FONT SIZE=2>Sent: Thursday, January 11, 2001 8:52 PM</FONT>
<BR><FONT SIZE=2>To: Jeff Roberson</FONT>
<BR><FONT SIZE=2>Cc: 'freebsd-current@freebsd.org'</FONT>
<BR><FONT SIZE=2>Subject: Re: Broken mmap in current?</FONT>
</P>
<BR>

<P><FONT SIZE=2>On Thu, 11 Jan 2001, Jeff Roberson wrote:</FONT>
</P>

<P><FONT SIZE=2>&gt; I have written a character device driver for a proprietary PCI device that</FONT>
<BR><FONT SIZE=2>&gt; has a large sum of mapable memory.&nbsp; The character device supports mmap()</FONT>
<BR><FONT SIZE=2>&gt; which I use to export the memory into a user process.&nbsp; I have no problems</FONT>
<BR><FONT SIZE=2>&gt; accessing the memory on this device, but I notice that my mmap routine is</FONT>
<BR><FONT SIZE=2>&gt; called for every access!&nbsp; Is this a problem with current, or a problem with</FONT>
<BR><FONT SIZE=2>&gt; my mmap?</FONT>
</P>

<P><FONT SIZE=2>Maybe both.&nbsp; The device mmap routine is called mainly by the mmap</FONT>
<BR><FONT SIZE=2>syscall for every page to be mmapped.&nbsp; It is also called by</FONT>
<BR><FONT SIZE=2>dev_pager_getpages() for some pagefaults, but I think this rarely happens.</FONT>
</P>

<P><FONT SIZE=2>&gt; I use bus_alloc_resource and then rman_get_start to get the physical address</FONT>
<BR><FONT SIZE=2>&gt; in my attach, and then the mmap just returns atop(physical address).&nbsp; I</FONT>
<BR><FONT SIZE=2>&gt; assumed this is correct since I have verified with a logical analyzer that I</FONT>
<BR><FONT SIZE=2>&gt; am indeed writing to the memory on the device.</FONT>
</P>

<P><FONT SIZE=2>This is correct.&nbsp; I looked at some examples.&nbsp; Many drivers get this</FONT>
<BR><FONT SIZE=2>wrong by using i386_btop(), alpha_btop(), etc.&nbsp; (AFAIK, atop() is</FONT>
<BR><FONT SIZE=2>for addresses which are what we are converting here, btop() is for</FONT>
<BR><FONT SIZE=2>(byte) offsets, and the machine-dependent prefixes are a vestige of</FONT>
<BR><FONT SIZE=2>page clustering code that mostly went away 7 years ago.</FONT>
</P>

<P><FONT SIZE=2>&gt; Also, I noticed that the</FONT>
<BR><FONT SIZE=2>&gt; device's mmap interface does not provide any way to limit the size of the</FONT>
<BR><FONT SIZE=2>&gt; block being mapped?&nbsp; Can I specify the length of the region?</FONT>
</P>

<P><FONT SIZE=2>The length is implicitly PAGE_SIZE.&nbsp; The device mmap function is called</FONT>
<BR><FONT SIZE=2>for each page to be mapped.&nbsp; It must verify that the memory from offset</FONT>
<BR><FONT SIZE=2>to (offset + PAGE_SIZE - 1) belongs to the device and can be accessed</FONT>
<BR><FONT SIZE=2>with the given protection, and do any device-specific things necessary to</FONT>
<BR><FONT SIZE=2>enable this memory.&nbsp; This scheme can't support bank-switched device</FONT>
<BR><FONT SIZE=2>memory very well, if at all.</FONT>
</P>

<P><FONT SIZE=2>pcvvt_mmap() in the pcvt driver is the simplest example of this.</FONT>
<BR><FONT SIZE=2>agp_mmap() is a more up to date example with the same old bug that the</FONT>
<BR><FONT SIZE=2>vga drivers used to have (off by 1 (page) error checking the offset).</FONT>
</P>

<P><FONT SIZE=2>Bruce</FONT>
</P>
<BR>
<BR>

<P><FONT SIZE=2>To Unsubscribe: send mail to majordomo@FreeBSD.org</FONT>
<BR><FONT SIZE=2>with &quot;unsubscribe freebsd-current&quot; in the body of the message</FONT>
</P>

</BODY>
</HTML>
home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?31E4B6337A4FD411BD45000102472E0C05E72A>