582 lines
		
	
	
	
		
			26 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			582 lines
		
	
	
	
		
			26 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| <!-- $Id: hackers.sgml,v 1.16 1999-04-09 15:43:23 des Exp $ -->
 | |
| <!-- The FreeBSD Documentation Project -->
 | |
| 
 | |
|   <sect>
 | |
|     <heading>For serious FreeBSD hackers only<label id="hackers"></heading>
 | |
| 
 | |
|     <sect1>
 | |
|       <heading>
 | |
|         What are SNAPs and RELEASEs?
 | |
|       </heading>
 | |
| 
 | |
|       <p>There are currently three active/semi-active branches in the FreeBSD
 | |
|       <url url="http://www.freebsd.org/cgi/cvsweb.cgi" name="CVS Repository">:
 | |
| 
 | |
|       <itemize>
 | |
|         <item><bf/RELENG_2_2/   AKA <bf/2.2-stable/ AKA <bf/"2.2 branch"/
 | |
|         <item><bf/RELENG_3/     AKA <bf/3.x-stable/ AKA <bf/"3.0 branch"/
 | |
|         <item><bf/HEAD/         AKA <bf/-current/ AKA <bf/4.0-current/
 | |
|       </itemize>
 | |
| 
 | |
|       <p><bf/HEAD/ is not an actual branch tag, like the other two, it's
 | |
|       simply a symbolic constant for
 | |
|       <em/"the current, non-branched development stream"/ which we simply
 | |
|       refer to as <bf/-current/.
 | |
| 
 | |
|       <p>Right now, <bf/-current/ is the 4.0 development stream and the
 | |
|       <bf/3.0-stable/ branch, <bf/RELENG_3/, forked off from
 | |
|       <bf/-current/ in Jan 1999.
 | |
| 
 | |
|       <p>The <bf/2.2-stable/ branch, <bf/RELENG_2_2/, departed -current in
 | |
|       November 1996.
 | |
| 
 | |
|       <p>The <bf/2.1-stable/ branch, <bf/RELENG_2_1_0/, departed -current in
 | |
|       September of 1994.  This branch has been fully retired.
 | |
| 
 | |
|     <sect1>
 | |
|       <heading>
 | |
|         How do I make my own custom release?<label id="custrel">
 | |
|       </heading>
 | |
| 
 | |
|       <p>To make a release you need to do three things: First, you need to
 | |
|       be running a kernel with the <htmlurl 
 | |
|       url="http://www.freebsd.org/cgi/man.cgi?vn" name="vn"> driver configured
 | |
|       in.  Add this to your kernel config file and build a new kernel:
 | |
| 
 | |
|       <verb>
 | |
|         pseudo-device vn         #Vnode driver (turns a file into a device)
 | |
|       </verb>
 | |
| 
 | |
|       <p>Second, you have to have the whole CVS repository at hand.
 | |
|       To get this you can use <url url="../handbook/synching.html#CVSUP" name="CVSUP">
 | |
|       but in your supfile set the release name to cvs and remove any tag or
 | |
|       date fields:
 | |
| 
 | |
|       <verb>
 | |
|         *default prefix=/home/ncvs
 | |
|         *default base=/a
 | |
|         *default host=cvsup.FreeBSD.org
 | |
|         *default release=cvs
 | |
|         *default delete compress use-rel-suffix
 | |
| 
 | |
|         ## Main Source Tree
 | |
|         src-all
 | |
|         src-eBones
 | |
|         src-secure
 | |
| 
 | |
|         # Other stuff
 | |
|         ports-all
 | |
|         www
 | |
|         doc-all
 | |
|       </verb>
 | |
| 
 | |
|       <p>Then run <tt/cvsup -g supfile/ to suck all the good bits onto your
 | |
|       box...
 | |
| 
 | |
|       <p>Finally, you need a chunk of empty space to build into. Let's
 | |
|       say it's in <tt>/some/big/filesystem</tt>, and from the example
 | |
|       above you've got the CVS repository in <tt>/home/ncvs</tt>:
 | |
| 
 | |
|       <verb>
 | |
|         setenv CVSROOT /home/ncvs        # or export CVSROOT=/home/ncvs
 | |
|         cd /usr/src/release
 | |
|         make release BUILDNAME=3.0-MY-SNAP CHROOTDIR=/some/big/filesystem/release
 | |
|       </verb>
 | |
| 
 | |
|       <p>An entire release will be built in
 | |
|       <tt>/some/big/filesystem/release</tt> and you will have a full FTP-type
 | |
|       installation in <tt>/some/big/filesystem/release/R/ftp</tt> when you're
 | |
|       done.  If you want to build your SNAP along some other branch than
 | |
|       -current, you can also add <tt/RELEASETAG=SOMETAG/ to
 | |
|       the make release command line above, e.g. <tt/RELEASETAG=RELENG_2_2/
 | |
|       would build an up-to-the- minute 2.2-STABLE snapshot.
 | |
| 
 | |
|     <sect1>
 | |
|       <heading>How do I create customized installation disks?</heading>
 | |
| 
 | |
|       <p>The entire process of creating installation disks and source and
 | |
|       binary archives is automated by various targets in
 | |
|       <tt>/usr/src/release/Makefile</tt>.  The information there should
 | |
|       be enough to get you started.  However, it should be said that this
 | |
|       involves doing a ``make world'' and will therefore take up a lot of
 | |
|       time and disk space.
 | |
| 
 | |
|     <sect1>
 | |
|       <heading>``make world'' clobbers my existing installed binaries.</heading>
 | |
| 
 | |
|       <p>Yes, this is the general idea; as its name might suggest,
 | |
|       ``make world'' rebuilds every system binary from scratch, so you can be
 | |
|       certain of having a clean and consistent environment at the end (which
 | |
|       is why it takes so long).
 | |
| 
 | |
|       <p>If the environment variable <tt/DESTDIR/ is defined while running
 | |
|       ``<tt/make world/'' or ``<tt/make install/'', the newly-created
 | |
|       binaries will be deposited in a directory tree identical to the
 | |
|       installed one, rooted at <tt>${DESTDIR}</tt>.
 | |
|       Some random combination of shared libraries modifications and
 | |
|       program rebuilds can cause this to fail in ``<tt/make world/'',
 | |
|       however.
 | |
| 
 | |
|     <sect1>
 | |
|       <heading>
 | |
|         When my system boots, it says ``(bus speed defaulted)''.
 | |
|       </heading>
 | |
| 
 | |
|       <p>The Adaptec 1542 SCSI host adapters allow the user to configure
 | |
|       their bus access speed in software.  Previous versions of the
 | |
|       1542 driver tried to determine the fastest usable speed and set
 | |
|       the adapter to that.  We found that this breaks some users'
 | |
|       systems, so you now have to define the ``<tt/TUNE_1542/'' kernel
 | |
|       configuration option in order to have this take place.  Using it
 | |
|       on those systems where it works may make your disks run faster,
 | |
|       but on those systems where it doesn't, your data could be
 | |
|       corrupted.
 | |
| 
 | |
|     <sect1>
 | |
|       <heading>
 | |
|         Can I follow current with limited Internet access?<label id="ctm">
 | |
|       </heading>
 | |
| 
 | |
|       <p>Yes, you can do this <tt /without/ downloading the whole source tree
 | |
|       by using the <url url="../handbook/synching.html#CTM" name="CTM facility.">
 | |
| 
 | |
|     <sect1>
 | |
|       <heading>How did you split the distribution into 240k files?</heading>
 | |
| 
 | |
|       <p>Newer BSD based systems have a ``<tt/-b/'' option to split that
 | |
|       allows them to split files on arbitrary byte boundaries.
 | |
| 
 | |
|       <p>Here is an example from <tt>/usr/src/Makefile</tt>.
 | |
| 
 | |
|       <verb>
 | |
|         bin-tarball:
 | |
|         (cd ${DISTDIR}; \
 | |
|         tar cf - . \
 | |
|         gzip --no-name -9 -c | \
 | |
|         split -b 240640 - \
 | |
|         ${RELEASEDIR}/tarballs/bindist/bin_tgz.)
 | |
|       </verb>
 | |
| 
 | |
|     <sect1>
 | |
|       <heading>I've written a kernel extension, who do I send it to?</heading>
 | |
| 
 | |
|       <p>Please take a look at <url url="../handbook/contrib.html"
 | |
|       name="The Handbook entry on how to submit code.">
 | |
| 
 | |
|       <p>And thanks for the thought!
 | |
| 
 | |
|     <sect1>
 | |
|       <heading>How are Plug N Play ISA cards detected and initialized?</heading>
 | |
| 
 | |
|       <p>By: <url url="mailto:uhclem@nemesis.lonestar.org"
 | |
|       name="Frank Durda IV">
 | |
| 
 | |
|       <p>In a nutshell, there a few I/O ports that all of the PnP boards
 | |
|       respond to when the host asks if anyone is out there.  So when
 | |
|       the PnP probe routine starts, he asks if there are any PnP boards
 | |
|       present, and all the PnP boards respond with their model # to
 | |
|       a I/O read of the same port, so the probe routine gets a wired-OR
 | |
|       ``yes'' to that question.  At least one bit will be on in that
 | |
|       reply.  Then the probe code is able to cause boards with board
 | |
|       model IDs (assigned by Microsoft/Intel) lower than X to go
 | |
|       ``off-line''.  It then looks to see if any boards are still
 | |
|       responding to the query.  If the answer was ``<tt/0/'', then
 | |
|       there are no boards with IDs above X.  Now probe asks if there
 | |
|       are any boards below ``X''.  If so, probe knows there are boards
 | |
|       with a model numbers below X.  Probe then asks for boards greater
 | |
|       than X-(limit/4) to go off-line.  If repeats the query.  By
 | |
|       repeating this semi-binary search of IDs-in-range enough times,
 | |
|       the probing code will eventually identify all PnP boards present
 | |
|       in a given machine with a number of iterations that is much lower
 | |
|       than what 2^64 would take.
 | |
| 
 | |
|       <p>The IDs are two 32-bit fields (hence 2ˆ64) + 8 bit checksum.
 | |
|       The first 32 bits are a vendor identifier.  They never come out
 | |
|       and say it, but it appears to be assumed that different types of
 | |
|       boards from the same vendor could have different 32-bit vendor
 | |
|       ids.  The idea of needing 32 bits just for unique manufacturers
 | |
|       is a bit excessive.
 | |
| 
 | |
|       <p>The lower 32 bits are a serial #, ethernet address, something
 | |
|       that makes this one board unique.  The vendor must never produce
 | |
|       a second board that has the same lower 32 bits unless the upper
 | |
|       32 bits are also different.  So you can have multiple boards of
 | |
|       the same type in the machine and the full 64 bits will still be
 | |
|       unique.
 | |
| 
 | |
|       <p>The 32 bit groups can never be all zero.  This allows the
 | |
|       wired-OR to show non-zero bits during the initial binary search.
 | |
| 
 | |
|       <p>Once the system has identified all the board IDs present, it will
 | |
|       reactivate each board, one at a time (via the same I/O ports),
 | |
|       and find out what resources the given board needs, what interrupt
 | |
|       choices are available, etc.  A scan is made over all the boards
 | |
|       to collect this information.
 | |
| 
 | |
|       <p>This info is then combined with info from any ECU files on the
 | |
|       hard disk or wired into the MLB BIOS.  The ECU and BIOS PnP
 | |
|       support for hardware on the MLB is usually synthetic, and the
 | |
|       peripherals don't really do genuine PnP.  However by examining
 | |
|       the BIOS info plus the ECU info, the probe routines can cause the
 | |
|       devices that are PnP to avoid those devices the probe code cannot
 | |
|       relocate.
 | |
| 
 | |
|       <p>Then the PnP devices are visited once more and given their I/O,
 | |
|       DMA, IRQ and Memory-map address assignments.  The devices will
 | |
|       then appear at those locations and remain there until the next
 | |
|       reboot, although there is nothing that says you can't move them
 | |
|       around whenever you want.
 | |
| 
 | |
|       <p>There is a lot of oversimplification above, but you should get
 | |
|       the general idea.
 | |
| 
 | |
|       <p>Microsoft took over some of the primary printer status ports to
 | |
|       do PnP, on the logic that no boards decoded those addresses for
 | |
|       the opposing I/O cycles.  I found a genuine IBM printer board
 | |
|       that did decode writes of the status port during the early PnP
 | |
|       proposal review period, but MS said ``tough''.  So they do a
 | |
|       write to the printer status port for setting addresses, plus that
 | |
|       use that address + <tt/0x800/, and a third I/O port for reading
 | |
|       that can be located anywhere between <tt/0x200/ and <tt/0x3ff/.
 | |
| 
 | |
|     <sect1>
 | |
|       <heading>Does FreeBSD support architectures other than the x86?</heading>
 | |
| 
 | |
|       <p>Several groups of people have expressed interest in working on
 | |
|       multi-architecture ports for FreeBSD and the FreeBSD/AXP (ALPHA)
 | |
|       port is one such effort which has been quite successful, now
 | |
|       available in 3.0 SNAPshot release form at <url
 | |
|       url="ftp://ftp.freebsd.org/pub/FreeBSD/alpha/"
 | |
|       name="ftp://ftp.freebsd.org/pub/FreeBSD/alpha">.  The ALPHA
 | |
|       port currently runs  on a growing number of ALPHA machine
 | |
|       types, among them the AlphaStation, AXPpci, PC164, Miata and Multia
 | |
|       models.  This port is not yet considered a full release and won't be
 | |
|       until a full compliment of system installation tools and a distribution
 | |
|       on CDROM installation media is available, including a reasonable
 | |
|       number of working ports and packages.
 | |
|       FreeBSD/AXP should be considered BETA quality software at this
 | |
|       time.  For status information, please join the
 | |
|       <tt><freebsd-alpha@FreeBSD.ORG></tt><ref id="mailing"
 | |
|       name="mailing list">.
 | |
| 
 | |
|       Interest has also been expressed in a port of FreeBSD to
 | |
|       the SPARC architecture, join the <tt><freebsd-sparc@FreeBSD.ORG>
 | |
|       </tt><ref id="mailing" name="mailing list"> if you are interested
 | |
|       in joining that project.  For general discussion on new architectures,
 | |
|       join the <tt><freebsd-platforms@FreeBSD.ORG></tt>
 | |
|       <ref id="mailing" name="mailing list">.
 | |
| 
 | |
|     <sect1>
 | |
|       <heading>I need a major number for a device driver I've written.</heading>
 | |
| 
 | |
|       <p>This depends on whether or not you plan on making the driver
 | |
|       publicly available.  If you do, then please send us a copy of the
 | |
|       driver source code, plus the appropriate modifications to
 | |
|       <tt>files.i386</tt>, a sample configuration file entry, and the
 | |
|       appropriate <htmlurl url="http://www.freebsd.org/cgi/man.cgi?MAKEDEV"
 | |
|       name="MAKEDEV"> code to create any special files your device uses.  If
 | |
|       you do not, or are unable to because of licensing restrictions, then
 | |
|       character major number 32 and block major number 8 have been reserved
 | |
|       specifically for this purpose; please use them.  In any case, we'd
 | |
|       appreciate hearing about your driver on
 | |
|       <tt><freebsd-hackers@FreeBSD.ORG></tt>.
 | |
| 
 | |
| 
 | |
|     <sect1>
 | |
|       <heading>Alternative layout policies for directories</heading>
 | |
| 
 | |
|       <p>
 | |
|       In answer to the question of alternative layout policies for
 | |
|       directories, the scheme that is currently in use is unchanged
 | |
|       from what I wrote in 1983. I wrote that policy for the original
 | |
|       fast filesystem, and never revisited it. It works well at keeping
 | |
|       cylinder groups from filling up. As several of you have noted,   
 | |
|       it works poorly for find. Most filesystems are created from      
 | |
|       archives that were created by a depth first search (aka ftw).    
 | |
|       These directories end up being striped across the cylinder groups
 | |
|       thus creating a worst possible senario for future depth first    
 | |
|       searches. If one knew the total number of directories to be      
 | |
|       created, the solution would be to create (total / fs_ncg) per    
 | |
|       cylinder group before moving on. Obviously, one would have to    
 | |
|       create some heuristic to guess at this number. Even using a      
 | |
|       small fixed number like say 10 would make an order of magnitude
 | |
|       improvement. To differentiate restores from normal operation   
 | |
|       (when the current algorithm is probably more sensible), you    
 | |
|       could use the clustering of up to 10 if they were all done       
 | |
|       within a ten second window. Anyway, my conclusion is that this   
 | |
|       is an area ripe for experimentation.</p>
 | |
| 
 | |
|       <p>Kirk McKusick, September 1998</p>
 | |
| 
 | |
|     <sect1>
 | |
|       <heading>Making the most of a kernel panic</heading>
 | |
| 
 | |
|       <p>      
 | |
|       <em>[This section was extracted from a mail written by <url
 | |
|       url="mailto:wpaul@FreeBSD.ORG" name="Bill Paul"> on the
 | |
|       freebsd-current <ref id="mailing" name="mailing list"> by <url
 | |
|       url="mailto:des@FreeBSD.ORG" name="Dag-Erling Coïdan
 | |
|       Smørgrav">, who fixed a few typos and added the bracketed
 | |
|       comments]</em>
 | |
| 
 | |
|       <p>
 | |
|       <verb>
 | |
| From: Bill Paul <wpaul@skynet.ctr.columbia.edu>
 | |
| Subject: Re: the fs fun never stops
 | |
| To: ben@rosengart.com
 | |
| Date: Sun, 20 Sep 1998 15:22:50 -0400 (EDT)
 | |
| Cc: current@FreeBSD.ORG
 | |
|       </verb>
 | |
| 
 | |
|       <p>
 | |
|       <em>[<ben@rosengart.com> posted the following panic
 | |
|       message]</em>
 | |
|       <verb>
 | |
| > Fatal trap 12: page fault while in kernel mode
 | |
| > fault virtual address   = 0x40
 | |
| > fault code              = supervisor read, page not present
 | |
| > instruction pointer     = 0x8:0xf014a7e5
 | |
|                                 ^^^^^^^^^^
 | |
| > stack pointer           = 0x10:0xf4ed6f24
 | |
| > frame pointer           = 0x10:0xf4ed6f28
 | |
| > 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         = 80 (mount)
 | |
| > interrupt mask          =
 | |
| > trap number             = 12
 | |
| > panic: page fault
 | |
|       </verb>
 | |
|       
 | |
|       <p> [When] you see a message like this, it's not enough to just
 | |
|       reproduce it and send it in. The instruction pointer value that
 | |
|       I highlighted up there is important; unfortunately, it's also
 | |
|       configuration dependent. In other words, the value varies
 | |
|       depending on the exact kernel image that you're using. If you're
 | |
|       using a GENERIC kernel image from one of the snapshots, then
 | |
|       it's possible for somebody else to track down the offending
 | |
|       function, but if you're running a custom kernel then only
 | |
|       <em/you/ can tell us where the fault occured.
 | |
| 
 | |
|       <p> What you should do is this:
 | |
| 
 | |
|       <itemize>
 | |
|         <item>Write down the instruction pointer value. Note that the
 | |
|         <tt/0x8:/ part at the begining is not significant in this case:
 | |
|         it's the <tt/0xf0xxxxxx/ part that we want.
 | |
| 	<item>When the system reboots, do the following:
 | |
| 	  <verb>
 | |
| % nm /kernel.that.caused.the.panic | grep f0xxxxxx
 | |
|           </verb>	  
 | |
| 	  where <tt/f0xxxxxx/ is the instruction pointer value. The
 | |
| 	  odds are you will not get an exact match since the symbols
 | |
| 	  in the kernel symbol table are for the entry points of
 | |
| 	  functions and the instruction pointer address will be
 | |
| 	  somewhere inside a function, not at the start. If you don't
 | |
| 	  get an exact match, omit the last digit from the instruction
 | |
| 	  pointer value and try again, i.e.:
 | |
| 	  <verb>
 | |
| % nm /kernel.that.caused.the.panic | grep f0xxxxx
 | |
| 	  </verb>
 | |
| 	  If that doesn't yield any results, chop off another digit.
 | |
| 	  Repeat until you get some sort of output. The result will be
 | |
| 	  a possible list of functions which caused the panic. This is
 | |
| 	  a less than exact mechanism for tracking down the point of
 | |
| 	  failure, but it's better than nothing.
 | |
|       </itemize>
 | |
| 
 | |
|       <p> I see people constantly show panic messages like this but
 | |
|       rarely do I see someone take the time to match up the
 | |
|       instruction pointer with a function in the kernel symbol table.
 | |
| 
 | |
|       <p> The best way to track down the cause of a panic is by
 | |
|       capturing a crash dump, then using <tt/gdb(1)/ to to a stack
 | |
|       trace on the crash dump. Of course, this depends on <tt/gdb(1)/
 | |
|       in -current working correctly, which I can't guarantee (I recall
 | |
|       somebody saying that the new ELF-ized <tt/gdb(1)/ didn't handle
 | |
|       kernel crash dumps correctly: somebody should check this before
 | |
|       3.0 goes out of beta or there'll be a lot of red faces after the
 | |
|       CDs ship).
 | |
| 
 | |
|       <p>
 | |
|       In any case, the method I normally use is this:
 | |
| 
 | |
|       <itemize>
 | |
|         <item>Set up a kernel config file, optionally adding 'options DDB' if you
 | |
| 	think you need the kernel debugger for something. (I use this mainly
 | |
| 	for setting beakpoints if I suspect an infinite loop condition of
 | |
| 	some kind.)
 | |
|         <item>Use <tt/config -g KERNELCONFIG/ to set up the build directory.
 | |
|         <item><tt>cd /sys/compile/KERNELCONFIG; make</tt>
 | |
|         <item>Wait for kernel to finish compiling.
 | |
|         <item><tt/cp kernel kernel.debug/
 | |
|         <item><tt/strip -d kernel/
 | |
|         <item><tt/mv /kernel /kernel.orig/
 | |
|         <item><tt>cp kernel /</tt>
 | |
|         <item>reboot
 | |
|       </itemize>
 | |
| 
 | |
|       <p> <em>[Note: Now that FreeBSD 3.x kernels are Elf by default,
 | |
|       you should use <tt/strip -g/ instead of <tt/strip -d/. If for some
 | |
|       reason your kernel is still a.out, use <tt/strip -aout -d/.]</em>
 | |
| 
 | |
|       <p> Note that YOU DO <em/NOT/ WANT TO ACTUALLY BOOT THE KERNEL
 | |
|       WITH ALL THE DEBUG SYMBOLS IN IT. A kernel compiled with <tt/-g/
 | |
|       can easily be close to 10MB in size. You don't have to actually
 | |
|       boot this massive image: you only need it later for <tt/gdb(1)/
 | |
|       (<tt/gdb(1)/ wants the symbol table). Instead, you want to keep
 | |
|       a copy of the full image and create a second image with the
 | |
|       debug symbols stripped out using <tt/strip -d/. It is this
 | |
|       second stripped image that you want to boot.
 | |
| 
 | |
|       <p> To make sure you capture a crash dump, you need edit
 | |
|       <tt>/etc/rc.conf</tt> and set <tt/dumpdev/ to point to your swap
 | |
|       partition. This will cause the <tt/rc(8)/ scripts to use the
 | |
|       <tt/dumpon(8)/ command to enable crash dumps. You can also run
 | |
|       <tt/dumpon(8)/ manually. After a panic, the crash dump can be
 | |
|       recovered using <tt/savecore(8)/; if <tt/dumpdev/ is set in
 | |
|       <tt>/etc/rc.conf</tt>, the <tt/rc(8)/ scripts will run
 | |
|       <tt/savecore(8)/ automatically and put the crash dump in
 | |
|       <tt>/var/crash</tt>.
 | |
| 
 | |
|       <p> NOTE: FreeBSD crash dumps are usually the same size as the
 | |
|       physical RAM size of your machine. That is, if you have 64MB of
 | |
|       RAM, you will get a 64MB crash dump. Therefore you must make sure
 | |
|       there's enough space in <tt>/var/crash</tt> to hold the dump.
 | |
|       Alternatively, you run <tt/savecore(8)/ manually and have it
 | |
|       recover the crash dump to another directory where you have more
 | |
|       room. It's possible to limit the size of the crash dump by using
 | |
|       <tt/options MAXMEM=(foo)/ to set the amount of memory the kernel
 | |
|       will use to something a little more sensible. For example, if
 | |
|       you have 128MB of RAM, you can limit the kernel's memory usage
 | |
|       to 16MB so that your crash dump size will be 16MB instead of
 | |
|       128MB.
 | |
| 
 | |
|       <p> Once you have recovered the crash dump, you can get a stack
 | |
|       trace with <tt/gdb(1)/ as follows:
 | |
| 
 | |
|       <p>
 | |
|       <verb>
 | |
| % gdb -k /sys/compile/KERNELCONFIG/kernel.debug /var/crash/vmcore.0
 | |
| (gdb) where
 | |
|       </verb>
 | |
| 
 | |
|       <p> Note that there may be several screens worth of information;
 | |
|       ideally you should use <tt/script(1)/ to capture all of them.
 | |
|       Using the unstripped kernel image with all the debug symbols
 | |
|       should show the exact line of kernel source code where the panic
 | |
|       occured. Usually you have to read the stack trace from the
 | |
|       bottom up in order to trace the exact sequence of events that
 | |
|       lead to the crash. You can also use <tt/gdb(1)/ to print out the
 | |
|       contents of various variables or structures in order to examine
 | |
|       the system state at the time of the crash.
 | |
| 
 | |
|       <p> Now, if you're really insane and have a second computer, you
 | |
|       can also configure <tt/gdb(1)/ to do remote debugging such that
 | |
|       you can use <tt/gdb(1)/ on one system to debug the kernel on
 | |
|       another system, including setting breakpoints, single-stepping
 | |
|       through the kernel code, just like you can do with a normal
 | |
|       user-mode program. I haven't played with this yet as I don't
 | |
|       often have the chance to set up two machines side by side for
 | |
|       debugging purposes.
 | |
| 
 | |
|       <p> <em>[Bill adds: "I forgot to mention one thing: if you have
 | |
|       DDB enabled and the kernel drops into the debugger, you can
 | |
|       force a panic (and a crash dump) just by typing 'panic' at the
 | |
|       ddb prompt. It may stop in the debugger again during the panic
 | |
|       phase. If it does, type 'continue' and it will finish the crash
 | |
|       dump." -ed]</em>
 | |
| 
 | |
|     <sect1>
 | |
|       <heading>dlsym() stopped working for ELF executables!</heading>
 | |
| 
 | |
|       <p>The ELF toolchain does not, by default, make the symbols 
 | |
|       defined in an executable visible to the dynamic linker.  
 | |
|       Consequently <tt>dlsym()</tt> searches on handles obtained 
 | |
|       from calls to <tt>dlopen(NULL, flags)</tt> will fail to find
 | |
|       such symbols.
 | |
| 
 | |
|       <p>If you want to search, using <tt>dlsym()</tt>, for symbols 
 | |
|       present in the main executable of a process, you need to link 
 | |
|       the executable using the <tt>-export-dynamic</tt> option to the
 | |
|       <htmlurl url="http://www.freebsd.org/cgi/man.cgi?ld" 
 | |
|       name="ELF linker">.
 | |
| 
 | |
|       
 | |
|     <sect1>
 | |
|       <heading>Increasing or reducing the kernel address space</heading>
 | |
| 
 | |
|       <p>
 | |
|       By default, the kernel address space is 256 MB on FreeBSD 3.x
 | |
|       and 1 GB on FreeBSD 4.x. If you run a network-intensive server
 | |
|       (e.g. a large FTP or HTTP server), you might find that 256 MB is
 | |
|       not enough.
 | |
| 
 | |
|       <p>
 | |
|       So how do you increase the address space? There are two aspects
 | |
|       to this. First, you need to tell the kernel to reserve a larger
 | |
|       portion of the address space for itself. Second, since the
 | |
|       kernel is loaded at the top of the address space, you need to
 | |
|       lower the load address so it doesn't bump its head against the
 | |
|       ceiling.
 | |
| 
 | |
|       <p>
 | |
|       The first goal is achieved by increasing the value of
 | |
|       <tt/NKPDE/ in <tt>src/sys/i386/include/pmap.h</tt>. Here's what
 | |
|       it looks like for a 1 GB address space:
 | |
| 
 | |
|       <verb>
 | |
| #ifndef NKPDE
 | |
| #ifdef SMP
 | |
| #define NKPDE                   254     /* addressable number of page tables/pde's */
 | |
| #else
 | |
| #define NKPDE                   255     /* addressable number of page tables/pde's */
 | |
| #endif  /* SMP */
 | |
| #endif
 | |
|       </verb>
 | |
| 
 | |
|       <p>
 | |
|       To find the correct value of <tt/NKPDE/, divide the desired
 | |
|       address space size (in megabytes) by four, then subtract one for
 | |
|       UP and two for SMP.
 | |
| 
 | |
|       <p>
 | |
|       To achieve the second goal, you need to compute the correct load
 | |
|       address: simply subtract the address space size (in bytes) from
 | |
|       0x100100000; the result is 0xc0100000 for a 1 GB address space.
 | |
|       Set <tt/LOAD_ADDRESS/ in <tt>src/sys/i386/conf/Makefile.i386</tt>
 | |
|       to that value; then set the location counter in the beginning of
 | |
|       the section listing in <tt>src/sys/i386/conf/kernel.script</tt>
 | |
|       to the same value, as follows:
 | |
| 
 | |
|       <verb>
 | |
| OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
 | |
| OUTPUT_ARCH(i386)
 | |
| ENTRY(btext)
 | |
| SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/obj/elf/home/src/tmp/usr/i386-unknown-freebsdelf/lib);
 | |
| SECTIONS
 | |
| {
 | |
|   /* Read-only sections, merged into text segment: */
 | |
|   . = 0xc0100000 + SIZEOF_HEADERS;
 | |
|   .interp     : { *(.interp)    }
 | |
|       </verb>
 | |
| 
 | |
|       <p>
 | |
|       Then reconfig and rebuild your kernel. You will probably have
 | |
|       problems with <tt/ps(1)/, <tt/top(1)/ and the like; <tt/make
 | |
|       world/ should take care of it (or a manual rebuild of
 | |
|       <tt/libkvm/, <tt/ps/ and <tt/top/ after copying the patched
 | |
|       <tt/pmap.h/ to <tt>/usr/include/vm/</tt>.
 | |
|       
 | |
|       <p>
 | |
|       NOTE: the size of the kernel address space must be a multiple of
 | |
|       four megabytes.
 | |
| 
 | |
|       <p>
 | |
|       [<url url="mailto:dg@freebsd.org" name="David Greenman">
 | |
|       adds: <em> I think the kernel address space needs to be a power
 | |
|       of two, but I'm not certain about that. The old(er) boot code
 | |
|       used to monkey with the high order address bits and I think
 | |
|       expected at least 256MB granularity.]</em>
 | |
| 
 | |
|   </sect>
 |