--- building.mm	2002/03/28 05:32:41	4.1
+++ building.mm	2003/04/17 02:20:58
@@ -1,39 +1,44 @@
 .\" This file is in -*- nroff-fill -*- mode
-.\" STATUS: review draft 4th edition
+.\" STATUS: 4th edition
 .\"
 .\" To do: add info about disabled devices
 .\"
-.\" $Id: building.mm,v 4.1 2002/03/28 05:32:41 grog Exp $
-.Chapter \*[nchbuild] "Configuring the kernel"
+.\" $Id: building.mm,v 4.17 2003/04/03 02:48:25 grog Exp grog $
+.Chapter \*[nchbuild] "Custom kernels"
 So far, everything we've done has been with the standard \f(CWGENERIC\fP kernel
-distributed with FreeBSD.  You may find advantages in a custom kernel:
+distributed with FreeBSD.  You may find it an advantage to install a custom
+kernel:
 .Ls B
 .LI
-.X "command, tcpdump"
-.X "tcpdump, command"
-.X "Berkeley Packet Filter"
-As we saw in \*[chconcepts], \f(CWGENERIC\fP doesn't support everything that
-FreeBSD knows about.  For example, if you want to install a Yoyodyne frobulator,
-you'll need to install special support for it.
-.Aside
+As we saw in Chapter
+.Sref \*[nchconcepts] ,
+\f(CWGENERIC\fP doesn't support everything that FreeBSD knows about.  For
+example, if you want to install a Yoyodyne frobulator, you'll need to install
+special support for it.\*F
+.FS
 In fact, the developer working on the Yoyodyne has defected to the Free Software
 Foundation.  See the GNU General Public License for further details.
-.End-aside
-.sp -.4v
+.FE
 .LI
 It will take less time to boot because it does not have to spend time probing
-for hardware which you do not have.
+for hardware that you do not have.
 .LI
 A custom kernel often uses less memory.  The kernel is the one system component
-which must always be present in memory, so unused code ties up memory which
+that must always be present in memory, so unused code ties up memory that
 would otherwise be available to the virtual memory system.  On a system with
-limited RAM, you can save some memory by building a custom kernel.  Don't
+limited RAM, you can save some memory by building a custom kernel, but don't
 overestimate the savings: a minimal kernel might save 500 kB over the
 \f(CWGENERIC\fP kernel supplied with the system.
 .LI
-Finally, there are several kernel options which you can tune to fit your needs.
+In addition, there are several kernel options that you can tune to fit your
+needs.
+.LI
+Finally, on page
+.Sref "\*[current]" \&
+we'll look at things to think about if you want to run the \f(CW-CURRENT\fP
+version of FreeBSD.
 .Le
-.X "Kernel Loadable Module"
+.X "kernel loadable module"
 .X "kld"
 In older releases of BSD, you needed to build a new kernel for just about
 anything you wanted to change, even things as simple as a different IRQ for a
@@ -44,26 +49,37 @@
 .Ls B
 .LI
 If you just need to add device support, you may be able to load a \fIKernel
-Loadable Module\fP, or \fIkld\fP.  See page \*[kld] for more information on
+Loadable Module\fP, or \fIkld\fP.  See page
+.Sref \*[kld] \&
+for more information on
 klds.
 .LI
-A number of kernel options have been replaced by the \fIsysctl\fP\| interface.
+If you want to change ISA parameters such as I/O address, IRQ or DMA settings,
+you no longer need to build a new kernel: the kernel configuration file no
+longer knows about such parameters.  Instead, they're in the file
+.File /boot/device.hints ,
+that we'll look at below.
+.LI
+A number of kernel options have been replaced by the \fIsysctl\fP\/ interface.
 For example, the \f(CWGENERIC\fP kernel does not perform packet routing by
-default.  In older versions of FreeBSD, you had to build a new kernel with the
+default.  In older releases of FreeBSD, you had to build a new kernel with the
 option \f(CWGATEWAY\fP.  Nowadays you can turn this feature on and off at will
-with a \fIsysctl\fP\| command.  We'll look at sysctls on page
-.Pn \*[sysctl] .
+with a \fIsysctl\fP\/ command.  We'll look at sysctls on page
+.Sref \*[sysctl] .
 .Le
 Configuring a kernel has changed a lot since the early days of FreeBSD, but it's
-not done yet.  In release 5 of FreeBSD, expected in late 2002 or early 2003,
-there will be further changes.  We'll look at them throughout this chapter.
+not done yet.  The information in this chapter represents a snapshot in the
+evolution of building kernels.  The goal of these changes is to make it
+unnecessary to build a kernel at all except to upgrade to a new release.
 .H2 "Building a new kernel"
 FreeBSD is distributed in source, and building a kernel primarily involves
 compiling the source files needed for the kernel.  To build a kernel, you
 perform the following steps:
 .Ls B
 .LI
-Install the system source, if you haven't already done so.
+Install the system source, if you haven't already done so.  We looked at that in
+Chapter
+.Sref \*[nchcurrent] .
 .LI
 .X "kernel, configuration file"
 Define your kernel configuration in a \fIkernel configuration file\fP.  This
@@ -71,78 +87,87 @@
 do this starting on page
 .Sref \*[configuration-file] .
 .LI
-.X "command, config"
-.X "config, command"
-Create the configuration directory with the program \fIconfig\fP.  We'll discuss
-this on page \*[run-config].
-.LI
-.X "make depend"
-Run \fImake depend\fP to create the dependency information for the kernel build.
-.LI
-Run \fImake\fP to build the kernel.  We'll look at this step on page
-.ie "\*[make-kernel]"\*[run-config]" .Sref \*[make-kernel] " too."
-.el .Sref \*[make-kernel] .
-.LI
-Install the kernel, which we'll discuss on page
-.Sref \*[install-kernel] .
+Change to the directory \fI/usr/src\fP\/ and run \fImake kernel\fP.  This builds
+and installs the kernel and all modules.  We'll look at it in more detail on
+page
+.Sref "\*[buildkernel]" ,
+where we'll also see alternatives that give more control over the process.
 .Le
 .H2 "Configuring I/O devices"
+.Pn IO-config
 A lot of the configuration file relates to the I/O devices that you may connect
-to your machine.  As we saw in \*[chconcepts], you will sometimes need to
-specify some of IRQ, DMA channel, board memory, and I/O addresses for the
-devices you configure, particularly for ISA boards.  The config file does not
-handle references to IRQ 2 correctly: you \fImust\fP\| specify them as IRQ 9.
-See page \*[IRQ] for further details.
-.P
-In FreeBSD version 5, you will no longer need to specify these values in the
-configuration file.  Instead, you should modify the file
-\fI/boot/device.hints\fP.  This file is not installed automatically.  If it
-doesn't exist, copy it from the configuration directory:
-.Dx
+to your machine.  In older releases of FreeBSD, it was often necessary to
+specify some of the IRQ, DMA channel, board memory, and I/O addresses for the
+devices you configure, particularly for ISA boards.  Since Release 5 of FreeBSD,
+this is no longer the case. Instead, you modify the file
+.File /boot/device.hints ,
+which we looked at on page
+.Sref \*[device-hints] .
+.P
+.ne 4v
+The kernel installation does not install
+.File /boot/device.hints
+automatically.  If it doesn't exist, copy it from the configuration directory:
+.Dx 1
 # \f(CBcp -p /usr/src/sys/i386/conf/GENERIC.hints  /boot/device.hints\fP
 .De
-.sp -1v
+.SPUP
 .H2 "The kernel build directory"
 .X "kernel, build directory"
-.X "/usr/src/sys"
-.X "/sys"
-.X "i386/conf"
-.X "alpha/conf"
-.X "/usr/src/sys/alpha/conf/LINT"
-The kernel sources are kept in the directory \fI/usr/src/sys\fP.  The symbolic
-link \fI/sys\fP also points to this directory.  There are a number of
-subdirectories of \fI/usr/src/sys\fP which represent different parts of the
-kernel, but for our purposes, the most important are the architecture dependent
-directories \fI/usr/src/sys/i386/conf\fP\| (for the i386 architecture) or
-\fI/usr/src/sys/alpha/conf\fP (for the Alpha architecture), where you edit your
-custom kernel configuration, and \fI/usr/src/sys/compile\fR, where you build
-your kernel.  In version 5 of FreeBSD, the compile directory will move down one
-level to \fI/usr/src/sys/alpha/compile\fR\| or \fI/usr/src/sys/i385/compile\fR.
-Notice the logical organization of the directory tree: each supported device,
-file system, and option has its own subdirectory.  In the rest of this chapter,
-we'll look at the i386 architecture.  Most of this applies to the Alpha
-architecture as well.
-.P
-.X "/usr/src/sys"
-If your system doesn't have the directory \fI/usr/src/sys\fP, then the kernel
-source has not been installed.  The sources are on the first CD-ROM in the
-directory \fI/src\fP.  To install from the CD-ROM, perform the following steps:
+The kernel sources are kept in the directory
+.Directory /usr/src/sys .
+The symbolic link
+.Directory /sys
+also points to this directory.  There are a number of subdirectories of
+.Directory /usr/src/sys
+that represent different parts of the kernel, but for our purposes, the most
+important of them are the architecture dependent directories such as
+.Directory /usr/src/sys/i386/conf
+(for the i386 architecture),
+.Directory /usr/src/sys/alpha/conf
+(for the Alpha architecture), or
+.Directory /usr/src/sys/sparc64/conf
+(for the SPARC64 architecture) where you edit your custom kernel configuration.
+In addition, the old style kernel build described below builds the kernel in the
+directory
+.Directory /usr/src/sys/i386/compile ,
+.Directory /usr/src/sys/alpha/compile
+or
+.Directory /usr/src/sys/sparc64/compile
+respectively.  Notice the logical organization of the directory tree: each
+supported device, file system, and option has its own subdirectory.  In the rest
+of this chapter, we'll look at the i386 architecture.  Most of this applies to
+other architectures as well.
+.P
+If your system doesn't have the directory
+.Directory /usr/src/sys ,
+the kernel source has not been installed.  If you have a CD-ROM, the sources are
+on the first CD-ROM in the directory
+.Directory /src .
+To install from the CD-ROM, perform the following steps:
 .Dx
 # \f(CBmkdir -p /usr/src/sys\f(CW
 # \f(CBln -s /usr/src/sys /sys\f(CW
 # \f(CBcd /\f(CW
 # \f(CBcat /cdrom/src/ssys.[a-h]* | tar xzvf -\f(CW
 .De
-The symbolic link \fI/sys\fP\| for \fI/usr/src/sys\fP\| is not strictly
-necessary, but it's a good idea: some software uses it, and otherwise you may
-end up with two different copies of the sources.
+The symbolic link
+.Directory /sys
+for
+.Directory /usr/src/sys
+is not strictly necessary, but it's a good idea: some software uses it, and
+otherwise you may end up with two different copies of the sources.
+.P
+By definition, the files on CD-ROM are out of date.  See Chapter
+.Sref \*[nchcurrent] \&
+for details of how to get the current, up-to-date sources.
 .P
 .X "kernel, GENERIC"
 Next, move to the directory \fIi386/conf\fR and copy the \fIGENERIC\fP
 configuration file to the name you want to give your kernel.  For example:
 .Dx
 # \f(CBcd /usr/src/sys/i386/conf\fP
-# cp \f(CBGENERIC FREEBIE\fP
+# \f(CBcp \f(CBGENERIC FREEBIE\fP
 .De
 .X "kernel, FREEBIE"
 Traditionally, this name is in all capital letters and, if you are maintaining
@@ -151,76 +176,102 @@
 .P
 .X "kernel, FREEBIE"
 .X "kernel, GENERIC"
-Now, edit \fIFREEBIE\fP with your favorite text editor.  Change the comment
+.ne 10v
+Now, edit \fIFREEBIE\fP with your favourite text editor.  Change the comment
 lines at the top to reflect your configuration or the changes you've made to
 differentiate it from \fIGENERIC\fP:
 .Dx
 #
 # \f(CBFREEBIE\fP -- \f(CBMy personal configuration file\fP
 #
-# For more information read the handbook part System Administration -> 
-# Configuring the FreeBSD Kernel -> The Configuration File. 
-# The handbook is available in /usr/share/doc/handbook or online as
-# latest version from the FreeBSD World Wide Web server 
-# <URL:http://www.FreeBSD.ORG/>
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+#    http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
 #
 # An exhaustive list of options and more detailed explanations of the 
-# device lines is present in the ./LINT configuration file. If you are 
-# in doubt as to the purpose or necessity of a line, check first in LINT.
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
 #
-#       $\&Id: \f(CBFREEBIE\fP,v 1.101 1997/10/31 22:10:02 jseger Exp $
+# $FreeBSD: src/sys/i386/conf/\f(CBFREEBIE\fP,v 1.369 2002/10/19 16:54:07 rwatson Exp $
 
 machine         "i386"
 cpu             "I486_CPU"
 cpu             "I586_CPU"
 cpu             "I686_CPU"
 ident           \f(CBFREEBIE\fP
-maxusers        10
+maxusers        0
 .De
 .X "kernel, GENERIC"
-If you've built a kernel under SunOS or some other BSD operating system, much of
-this file will be very familiar to you.  If you're coming from some other
-operating system such as MS-DOS, on the other hand, the \fIGENERIC\fP configuration
-file might seem overwhelming to you, so follow the descriptions in the following
-section slowly and carefully.
+.SPUP
+.br
+.\" XXX As long as this section starts with the table, this is needed to
+.\" XXX make it look right.
+.ne 13v
 .H2 "The configuration file"
 .X "kernel, configuration file"
 .X "configuration file, kernel"
 .Pn configuration-file
 .X "kernel, GENERIC"
 .X "kernel, LINT"
-The directory \fI/sys/i386/conf\fP\| contains a number of configuration files:
+The directory
+.Directory /sys/i386/conf
+contains a number of configuration files:
 .TS
 tab(#) ;
-lfCWp9 lw65 .
+lfCWp9 lw62 .
 GENERIC#T{
 General-purpose configuration file
 T}
+.sp .4v
 LINT#T{
-Complete configuration file with copious comments.  This file is intended for
-regression testing and documentation, not for building kernels, which would be
-far too bloated.
-.P
-Version 5 of FreeBSD will no longer supply a \f(CWLINT\fP configuration file.
-Instead it will supply a file \f(CWNOTES\fP\| in a slightly more legible format.
-You can use it to creat the \f(CWLINT\fP by running \fImake\fP\| in that
-directory.
+This file used to be a ``complete'' configuration file with comments, used for
+testing and documentation.  Since FreeBSD Release 5, it no longer exists.  You
+can create it from the files
+.File NOTES
+and
+.File /usr/src/sys/conf/NOTES
+with the command:
+.Dx
+$ \f(CBmake LINT\fP
+.De
 T}
-PCCARD#T{
-A configuration file for laptops which use PCCARD controllers.
+NOTES#T{
+A complete pseudo-configuration file with copious comments.  This file is
+descended from
+.File LINT ,
+but it also includes device hints.  You can't use it for building kernels.
+Instead, create the file
+.File LINT
+as described above.
+.P
+.File NOTES
+contains only platform-specific information.  Most of the information is in the
+platform-independent file
+.File /usr/src/sys/conf/NOTES .
 T}
-SMP-GENERIC#T{
-A generic configuration file for symmetrical multiprocessor machines.
+.sp .4v
+OLDCARD#T{
+A configuration file for laptops that use PCCARD controllers.  At the time of
+writing, PCCARD support has largely been rewritten, but the new code does not
+support some of the devices that the old code supports.  This configuration
+file uses the old PCCARD code instead of the new code.  When the new code is
+complete, it will go away.
 T}
 .TE
 .P
 The general format of a configuration file is quite simple.  Each line contains
-a keyword and one or more arguments.  For simplicity, most lines only contain
-one argument.  Anything following a \f(CW#\fR is considered a comment and
-ignored.  Keywords which contain numbers used as text must be enclosed in
-quotation marks.
+a keyword and one or more arguments.  Anything following a \f(CW#\fR is
+considered a comment and ignored.  Keywords that contain numbers used as text
+must be enclosed in quotation marks.
 .P
-One of the results of this simplicity is that you can put in options which have
+One of the results of this simplicity is that you can put in options that have
 absolutely no effect.  For example, you could add a line like this:
 .Dx
 .Pn config-APPLE_MAC_COMPATIBILITY
@@ -230,22 +281,26 @@
 Now it's unlikely that you'll think up a non-existent option like this, but it's
 much more possible that you'll misspell a valid option, especially
 finger-twisters like \f(CWSYSVSHM\fP, with the result that you don't compile in
-the option you wanted.  The \fIconfig\fP\| program warns if you use unknown
+the option you wanted.  The \fIconfig\fP\/ program warns if you use unknown
 options, so take these warnings seriously.
 .P
 Kernel options change from release to release, so there's no point in describing
 them all here.  In the following sections we'll look at some of the more
-interesting ones; for a complete list, read \f(CWLINT\fP or the online
-handbook.
+interesting ones; for a complete list, read
+.File LINT
+or the online handbook.  See above for details of how to create
+.File LINT .
 .H3 "Naming the kernel"
 .X "kernel, naming"
 Every kernel you build requires the keywords \f(CWmachine\fP, \f(CWcpu\fP, and
 \f(CWident\fP.  For example,
 .Dx
 .Pn config-i386
-machine         "i386"                          \fIFor i386 architecture\fP\|
+machine         "i386"                          \fIFor i386 architecture\fP\/
 .Pn config-alpha
-machine         "alpha"                         \fIFor alpha architecture\fP\|
+machine         "alpha"                         \fIFor alpha architecture\fP\/
+.Pn config-sparc64
+machine         "sparc64"                       \fIFor SPARC 64 architecture\fP\/
 .Pn config-I486_CPU
 cpu             "I486_CPU"
 .Pn config-I586_CPU
@@ -265,181 +320,406 @@
 with the processor: for example, the \f(CWi386\fP architecture refers to the
 Intel 80386 and all its successors, including lookalikes made by AMD, Cyrix and
 IBM.
-.H4 "cpu \fIcpu_type"
-.X "cpu \fIcpu_type"
+.H4 "cpu cpu_type"
+.X "cpu cpu_type"
 .Pn config-cpu
-\f(CWcpu\fR describes which CPU chip is to be supported by this kernel.  For the
-\f(CWi386\fP architecture, the possible values are \f(CWI386_CPU\fP,
+\f(CWcpu\fR describes which CPU chip or chips this kernel should support.  For
+the \f(CWi386\fP architecture, the possible values are \f(CWI386_CPU\fP,
 \f(CWI486_CPU\fP, \f(CWI586_CPU\fP and \f(CWI686_CPU\fP, and you can specify any
 combination of these values.  For a custom kernel, it is best to specify only
-the cpu you have.  If, for example, you have an Intel Pentium, use
+the CPU you have.  If, for example, you have an Intel Pentium, use
 \f(CWI586_CPU\fR for \fIcpu_type\fP.
 .P
-With release 5 of FreeBSD, it will not be possible to build a single kernel with
-support for both the 80386 processor and later processors.  You will need to
-choose either \f(CWI386_CPU\fP or any of the others.
-.H4 "ident \fImachine_name\fP"
-.X "ident \fImachine_name\fP"
+.ne 4v
+If you're not sure what processor type you have, look at the output from the
+.Command dmesg
+command when running the \f(CWGENERIC\fP kernel.  For example:
+.Dx
+CPU: AMD Athlon(tm) XP processor 1700+ (1462.51-MHz \f(CB686-class CPU\fP)
+  Origin = "AuthenticAMD"  Id = 0x662  Stepping = 2
+  Features=0x383f9ff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,SEP,MTRR,PGE,MCA,CMOV,PAT,PS
+E36,MMX,FXSR,SSE>
+  AMD Features=0xc0480000<<b19>,AMIE,DSP,3DNow!>
+.De
+This shows that the processor, an AMD Athlon XP, is a ``686 class'' CPU, so to
+run a kernel on this processor, you must set \f(CWI686_CPU\fP in the config
+file.
+.P
+Since Release 5 of FreeBSD, it is no longer possible to build a single kernel
+with support for both the 80386 processor and later processors: the code for the
+later processors is optimized to use instructions that the 80386 processor does
+not have.  Choose either \f(CWI386_CPU\fP or any combination of the others.
+.H4 "ident machine_name"
+.X "ident machine_name"
 .Pn config-ident
 .X "kernel, GENERIC"
 .X "kernel, FREEBIE"
 \f(CWident\fR specifies a name used to identify the kernel.  In the file
-\fIGENERIC\fP it is \f(CWGENERIC\fP.  Change this to whatever you named your
-kernel, in this example, \f(CWFREEBIE\fP.  The value you put in \f(CWident\fR
-will print when you boot up the kernel, so it's useful to give a kernel a
-different name if you want to keep it separate from your usual kernel (if you
-want to build an experimental kernel, for example).  As with \f(CWmachine\fR and
-\f(CWcpu\fR, enclose your kernel's name in quotation marks if it contains any
-numbers.
+.File GENERIC
+it is \f(CWGENERIC\fP.  Change this to whatever you named your kernel, in this
+example, \f(CWFREEBIE\fP.  The value you put in \f(CWident\fR will print when
+you boot up the kernel, so it's useful to give a kernel a different name if you
+want to keep it separate from your usual kernel (if you want to build an
+experimental kernel, for example).  As with \f(CWmachine\fR and \f(CWcpu\fR,
+enclose your kernel's name in quotation marks if it contains any numbers.
 .P
 This name is passed to the C compiler as a variable, so don't use names like
 \f(CWDEBUG\fR, or something that could be confused with another machine or CPU
 name, like \f(CWvax\fR.
-.H4 "maxusers \fInumber"
-.X "maxusers \fInumber"
-.Pn config-maxusers
-.X "error, proc table full"
-.X "Walnut Creek CDROM"
-.X "wcarchive.cdrom.com"
-This value sets the size of a number of important system tables.  It is intended
-to be roughly equal to the number of simultaneous users you expect to have on
-your machine.  However, even if you are the only person to use the machine, you
-shouldn't set \f(CWmaxusers\fR lower than the default value 32, especially if
-you're using X or compiling software.  The reason is that the most important
-table set by \f(CWmaxusers\fR is the maximum number of processes, which is set
-to \f(CW20\0+\016\0* maxusers\fP, so if you set \f(CWmaxusers\fR to one, then
-you can only have 36 simultaneous processes, including the 18 or so that the
-system starts up at boot time, and the 15 or so you will probably create when
-you start X.  Even a simple task like reading a man page can start up nine
-processes to filter, decompress, and view it.  Setting \f(CWmaxusers\fR to 32
-will allow you to have up to 532 simultaneous processes, which is normally
-ample.  If, however, you see the dreaded \fIproc table full\fP error when trying
-to start another program, or are running a server with a large number of
-simultaneous users, you can always increase this number and rebuild.
-.Aside
-\f(CWmaxusers\fR does \fInot\fP limit the number of users which can log into
-your machine.  It simply sets various table sizes to reasonable values
-considering the maximum number of users you will likely have on your system and
-how many processes each of them will be running.  One keyword which \fIdoes\fP
-limit the number of simultaneous \fIremote\fP logins is \f(CWpseudo-device
-pty\fP.
-.End-aside
-Nowadays you can specify the value 0 for \f(CWmaxusers\fP.  This allows the
-kernel to autosize the tables between the values 32 and 512, depending on the
-amount of memory on the system.
-.H4 "config \fIkernel_name\fP"
-Older versions of FreeBSD required a \f(CWconfig\fP line specifying the name of
-the kernel.  This is no longer allowed.  By default, the kernel is placed in
-\fI/kernel\fP\| on FreeBSD version 4, and in \fI/boot/kernel/kernel\fP\| in
-version 5.
 .H3 "Kernel options"
 .X "kernel, options"
 .X "options, kernel"
 There are a number of global kernel options, most of which you don't need to
-change.  There's one, though, that you should change.  By default, the
-\f(CWmakeoptions line is commented out\fP.  You should uncomment it:
-.Dx
-makeoptions     DEBUG=-g                # Build kernel with gdb(1) debug symbols
-.De
+change.  In the following section, we'll look at some of the few exceptions.
+.H4 "Configuring specific I/O devices"
+There are some devices that the \f(CWGENERIC\fP kernel does not support.  In
+older releases of FreeBSD, you needed to build a new kernel to support them.
+This is seldom the case any more: most devices can be supported by \fIkld\fP\/s.
+Work is under way to support the remainder.  In case of doubt, look at the file
+.File HARDWARE.TXT
+on the installation CD-ROM.
+.ig
+.\" XXX where has it gone?
+, or the file
+.File -n /stand/help/HARDWARE.TXT.gz
+on the installed system.
+..
+.H4 "maxusers number"
+.X "maxusers number"
+.Pn config-maxusers
+This value sets the size of a number of important system tables.  It is still
+included in the kernel configuration file, but you no longer need build a new
+kernel to change it.  Instead, you can set it at boot time.  For example, you
+might add the following line to your
+.File /boot/loader.conf
+file:
+.Dx 1
+maxusers="64"
+.De
+See
+.Sref "\*[io-config]" \&
+for more details of
+.File /boot/loader.conf .
+.P
+\f(CWmaxusers\fP is intended to be roughly equal to the number of simultaneous
+users you expect to have on your machine, but it is only used to determine the
+size of some system tables.  The default value 0 tells the kernel to autosize
+the tables depending on the amount of memory on the system.  If the autosizing
+doesn't work to your satisfaction, change this value.  Even if you are the only
+person to use the machine, you shouldn't set \f(CWmaxusers\fR lower than the
+default value 32, especially if you're using X or compiling software.  The
+reason is that the most important table set by \f(CWmaxusers\fR is the maximum
+number of processes, which is set to \f(CW20\0+\016\0* maxusers\fP, so if you
+set \f(CWmaxusers\fR to one, you can only have 36 simultaneous processes,
+including the 18 or so that the system starts up at boot time, and the 15 or so
+you will probably create when you start X.  Even a simple task like reading a
+man page can start up nine processes to filter, decompress, and view it.
+Setting \f(CWmaxusers\fR to 32 will allow you to have up to 532 simultaneous
+processes, which is normally ample.  If, however, you see the dreaded \fIproc
+table full\fP error when trying to start another program, or are running a
+server with a large number of simultaneous users, you can always increase this
+number and reboot.
 .Aside
-So why is it commented out?  The FreeBSD project couldn't agree to change it.
-See the discussion in \*[chproblems], page 
-.Sref \*[debug-kernel] .
+\f(CWmaxusers\fR does \fInot\fP limit the number of users who can log into the
+machine.  It simply sets various table sizes to reasonable values considering
+the maximum number of users you will likely have on your system and how many
+processes each of them will be running.  It's probable that this parameter will
+go away in future.
 .End-aside
-.sp -1v
 .H3 "Multiple processors"
-FreeBSD \*[Fver] supports most modern multiprocessor systems with i386
-architecture.  The \f(CWGENERIC\fP kernel does not support them by default: set
-the following options:
+FreeBSD \*[Fver] supports most modern multiprocessor systems.  The
+\f(CWGENERIC\fP kernel does not support them by default.  For i386, set the
+following options:
 .Dx
 # To make an SMP kernel, the next two are needed
 .Pn config-SMP
 .X "config option, SMP"
-.X "SMP, config option"
+.X "SMP, kernel option"
 options SMP                     # Symmetric MultiProcessor Kernel
 .Pn config-APIC_IO
 .X "config option, APIC_IO"
-.X "APIC_IO, config option"
+.X "APIC_IO, kernel option"
 options APIC_IO                 # Symmetric (APIC) I/O
 .De
-An SMP kernel will not run on a single processor machine without the IOAPIC
-chip.  Be sure to disable the \f(CWcpu "I386_CPU"\fP and \f(CWcpu "I486_CPU"\fP
-options for SMP kernels.
+For Alpha, only the first line is necessary:
+.Dx
+options         SMP                     # Symmetric MultiProcessor Kernel
+.De
+An SMP kernel will not run on a single processor Intel machine without an
+\fIIOAPIC\fP\/ (\fII/O Advanced Programmable Interrupt Controller\fP\/) chip.
+Be sure to disable the \f(CWcpu "I386_CPU"\fP and \f(CWcpu "I486_CPU"\fP options
+for SMP kernels.
+.H3 "Debug options"
+.Pn debug-kernel
+.X "kernel, options"
+.X "options, kernel"
+FreeBSD is a very stable operating system.  No software is perfect, however, and
+sometimes it crashes.  When it does, it provides a number of facilities to help
+fix the problem.  Some of these are dependent on kernel build options.
+.P
+Even if you have no intention of debugging a kernel problem yourself, you should
+set debug symbols when you build a kernel.  They cost nothing except disk space,
+and if you are short on disk space, you can remove most of the files after the
+build.
+.P
+.ne 3v
+To set the debug symbols, remove the leading \f(CW#\fP mark from this line in
+the configuration file:
+.Dx 1
+makeoptions     DEBUG=-g                # Build kernel with gdb(1) debug symbols
+.De
+Under normal circumstances this makes no difference: the build process still
+installs the kernel without the debug symbols, and it has no effect on
+performance.  If, however, you have a crash, the kernel with debug symbols is
+available in the kernel build directory, in this case
+.File /usr/src/sys/i386/compile/FREEBIE/kernel.debug ,
+to assist analysis of the problem.  Without this file it will be very difficult
+to find it.
+.P
+.ne 4v
+So why is it commented out?  Without debug symbols, your build directory will
+take about 50 MB of disk space.  With debug symbols, it will be about 250 MB.
+The FreeBSD Project couldn't agree to change it.
+.H4 "Other debugging options"
+If you run into trouble with your system, there are a number of other debugging
+options that you can use.  The following are the more important ones:
+.Dx
+.X "config option, DDB"
+.X "DDB, kernel option"
+options         DDB
+.X "config option, BREAK_TO_DEBUGGER"
+.X "BREAK_TO_DEBUGGER, kernel option"
+options         BREAK_TO_DEBUGGER
+.X "config option, DDB_UNATTENDED"
+.X "DDB_UNATTENDED, kernel option"
+options         DDB_UNATTENDED       # Don't drop into DDB for a panic
+.X "config option, GDB_REMOTE_CHAT"
+.X "GDB_REMOTE_CHAT, kernel option"
+options         GDB_REMOTE_CHAT      # Use \fIgdb\fP\/ remote debugging protocol
+.X "config option, KTRACE"
+.X "KTRACE, kernel option"
+options         KTRACE
+.X "config option, DIAGNOSTIC"
+.X "DIAGNOSTIC, kernel option"
+options         DIAGNOSTIC
+.X "config option, INVARIANTS"
+.X "INVARIANTS, kernel option"
+options         INVARIANTS
+.X "config option, INVARIANT_SUPPORT"
+.X "INVARIANT_SUPPORT, kernel option"
+options         INVARIANT_SUPPORT
+options         WITNESS              #Enable checks to detect deadlocks and cycles
+options         WITNESS_SKIPSPIN     #Don't run witness on spinlocks for speed
+.De
+These options provide support for various debugging features.
+.H4 "DDB"
+.X "DDB, kernel option"
+.Pn config-DDB
+.X "ddb"
+Specify \f(CWDDB\fP to include the kernel debugger, \fIddb\fP.  If you set this
+option, you might also want to set the \f(CWBREAK_TO_DEBUGGER\fP option,
+.H4 "BREAK_TO_DEBUGGER"
+.Pn config-BREAK_TO_DEBUGGER
+Use the option \f(CWBREAK_TO_DEBUGGER\fP if you have installed the kernel
+debugger and you have the system console on a serial line.
+.H4 "DDB_UNATTENDED"
+.Pn config-DDB_UNATTENDED
+If you have a panic on a system with \fIddb\fP, it will not reboot
+automatically.  Instead, it will enter \fIddb\fP\/ and give you a chance to
+examine the remains of the system before rebooting.  This can be a disadvantage
+on systems that run unattended: after a panic, they would wait until somebody
+comes past before rebooting.  Use the \f(CWDDB_UNATTENDED\fP option to cause a
+system with \fIddb\fP\/ to reboot automatically on panic.
+.H4 "GDB_REMOTE_CHAT"
+.Pn config-GDB_REMOTE_CHAT
+\fIddb\fP\/ supports remote debugging from another FreeBSD machine via a serial
+connection.  See the online handbook for more details.  To use this feature, set
+the option \f(CWGDB_REMOTE_CHAT\fP.
+.H4 "KTRACE"
+.Pn config-KTRACE
+.X "command, ktrace"
+.X "ktrace, command"
+Set \f(CWKTRACE\fP if you want to use the system call trace program \fIktrace\fP.
+.H4 "DIAGNOSTIC"
+.Pn config-DIAGNOSTIC
+.X "DIAGNOSTIC, kernel option"
+A number of source files use the \f(CWDIAGNOSTIC\fP option to enable extra sanity
+checking of internal structures.  This support is not enabled by default because
+of the extra time it would take to check for these conditions, which can only
+occur as a result of programming errors.
+.H4 "INVARIANTS and INVARIANT_SUPPORT"
+.Pn config-INVARIANTS
+.Pn config-INVARIANT_SUPPORT
+\f(CWINVARIANTS\fP is used in a number of source files to enable extra sanity
+checking of internal structures.  This support is not enabled by default because
+of the extra time it would take to check for these conditions, which can only
+occur as a result of programming errors.
+.P
+\f(CWINVARIANT_SUPPORT\fP option compiles in support for verifying some of the
+internal structures.  It is a prerequisite for \f(CWINVARIANTS\fP.  The intent
+is that you can set \f(CWINVARIANTS\fP for single source files (by changing the
+source file or specifying it on the command line) if you have
+\f(CWINVARIANT_SUPPORT\fP enabled.
+.H4 "WITNESS and WITNESS_SKIPSPIN"
+One of the big changes in FreeBSD Release 5 relates to the manner in which the
+kernel performs resource locking.  As a result, the danger exists of
+\fIdeadlocks\fP, locks that can't be undone without rebooting the machine.
+\f(CWWITNESS\fP checks for the danger of deadlocks and warns if it finds a
+potential deadlock (``lock order reversal'').  This is a very expensive
+debugging option: it can slow the machine down by an order of magnitude, so
+don't use it unless you have to.
+.P
+.ne 3v
+A compromise that doesn't use quite so much processor power is the combination
+of \f(CWWITNESS\fP with \f(CWWITNESS_SKIPSPIN\fP, which avoids spin locks.  It
+can still catch most problems.
+.\" XXX check for more debug options before publishing.
+.H2 "Preparing for upgrades"
+.Pn kernel-upgrade
+When changing the configuration file, consider that it probably won't be the
+only time you make these changes.  At some time in the future, you'll upgrade
+the system, and you'll have to build your custom kernel all over again.  But the
+\f(CWGENERIC\fP kernel configuration file will have changed as well.  You have
+two choices: incorporate the modifications to \f(CWGENERIC\fP into your
+configuration file, or incorporate your modifications to the old \f(CWGENERIC\fP
+file into the new \f(CWGENERIC\fP configuration file.  It turns out that the
+latter path is easier.
+.P
+To prepare for this approach, try to change as little as possible in the
+body of the configuration file.  Instead, add all your changes to the end, along
+with a comment so that you can readily recognize the changes.  For example, you
+might append:
+.Dx
+# Added by grog, 24 October 2002
+# Comment out WITNESS, WITNESS_SKIPSPIN and SCSI_DELAY above
+
+options         SMP                     # Symmetric MultiProcessor Kernel
+options         APIC_IO                 # Symmetric (APIC) I/O
+
+options         BREAK_TO_DEBUGGER
+
+options         SCSI_DELAY=3000         #Delay (in ms) before probing SCSI
+
+options         CAMDEBUG
+options         MSGBUF_SIZE=81920
+# options       TIMEREQUESTS            # watch for delays
+
+device          snp                     #Snoop device - to look at pty/vty/etc..
+.De
+That won't be all, of course.  Look at that option \f(CWSCSI_DELAY\fP.  That
+option already exists in the configuration file (with a value of 15 seconds
+instead of 3).  If you leave both,
+.Command config
+will issue a warning.  You need to comment out the first occurrence, as the
+comment at the top indicates.
 .H2 "Building and installing the new kernel"
 .X "kernel, building"
-.Pn run-config
-.X "command, config"
-.X "config, command"
-.X "/usr/src/sys/i386/conf"
-After editing the configuration file, you create the build environment with
-\fIconfig\fP.  In the directory \fI/usr/src/sys/i386/conf\fP, you enter:
-.Dx
-# \f(CB/usr/sbin/config FREEBIE\fP
-Kernel build directory is ../../compile/FREEBIE
-.De
-It's possible to get error messages when running \fIconfig\fP if you have made a
-mistake in the config file.  If the \fIconfig\fR command fails when you give it
-your kernel description, you've probably made a simple error somewhere.
-Fortunately, \fIconfig\fR will print the line number that it had trouble with,
-so you can quickly find it with an editor.  For example:
+.Pn buildkernel
+The traditional way to build a BSD kernel was, assuming a configuration file
+called
+.File -n FREEBIE \/:
 .Dx
+# \f(CBcd /usr/src/sys/i386/conf\fP
+# \f(CBconfig FREEBIE\fP
+# \f(CBcd ../compile/FREEBIE\fP
+# \f(CBmake depend all install\fP
+.De
+.ne 3v
+At the time of writing, this still works, but it will go away at some time in
+the future.  It has the disadvantage that you need to know your architecture,
+and the kernel is built in the source tree, which is not a good idea.  The new
+kernel build method starts from
+.Directory /usr/src ,
+the same directory as all other build operations, and it builds the kernel in
+the
+.Directory /usr/obj
+hierarchy.
+.P
+You'll need about 250 MB of free space on
+.Directory /usr/obj
+to build a kernel.  If you're really tight on space, you can reduce this value
+to about 50 MB by omitting the \f(CWmakeoptions DEBUG=-g\fP specification, but
+if you have problems with the system at some later stage, it will be much more
+difficult to find what is causing them.
+.P
+There are a number of alternative commands for building the kernel:
+.Dx
+# \f(CBcd /usr/src\fP
+# \f(CBmake kernel KERNCONF=FREEBIE\fP                   \fIbuild and install kernel and klds\fP\/
+# \f(CBmake buildkernel KERNCONF=FREEBIE\fP              \fIbuild kernel and klds\fP\/
+# \f(CBmake installkernel KERNCONF=FREEBIE\fP            \fIinstall prebuilt kernel and klds\fP\/
+# \f(CBmake reinstallkernel KERNCONF=FREEBIE\fP          \fIreinstall kernel and klds\fP\/
+# \f(CBmake kernel KERNCONF=FREEBIE -DNO_MODULES\fP      \fIbuild and install kernel only\fP\/
+.De
+The easiest way is \f(CWmake kernel\fP, which is subdivided into the
+\f(CWbuildkernel\fP and \f(CWinstallkernel\fP steps.  You can perform these
+steps individually if you want.  If you use the \f(CWreinstallkernel\fP target
+instead of the \f(CWinstallkernel\fP target, the
+.Directory /boot/kernel.old
+hierarchy remains unchanged.  This is useful when a previous kernel build failed
+to boot.
+.P
+If you know the klds are not going to change, you can speed things up by not
+building them again.  Use the \f(CW-DNO_MODULES\fP flag in combination with any
+of the other targets to inhibit building or installing the klds, as shown in the
+last example.  Don't do this the first time you build the kernel: if you have
+mismatches between the kernel and the klds, you may find it impossible to start
+the system.  On the other hand, if you find the kernel doesn't boot, and you
+want to change the configuration file and rebuild it from the same sources, you
+can save some time like this.
+.P
+The first step in building the kernel is to run the
+.Command config 
+program.  You no longer have to do this yourself; the \f(CWbuildkernel\fP and
+\f(CWkernel\fP targets do it for you.
+.Command config
+creates a directory in which to build the kernel and fills it with the necessary
+infrastructure, notably the kernel
+.File Makefile
+and a number of header files.
+.P
+It's possible to get error messages at this stage if you have made a mistake in
+the config file.  If the \fIconfig\fR command fails when you give it your kernel
+description, you've probably made a simple error somewhere.  Fortunately,
+\fIconfig\fR will print the line number that it had trouble with, so you can
+quickly find it with an editor.  For example:
+.Dx 1
 config: line 17: syntax error
 .De
+.ne 2v
 .X "kernel, GENERIC"
 One possibility is that you have mistyped a keyword.  Compare it to the entry in
 the \f(CWGENERIC\fP or \f(CWLINT\fP kernel definitions.
 .P
-You'll need about 50 MB of free space on \fI/usr/src\fP\| in order to build a
-kernel.  If you're really tight on space, you can reduce this value to about 10
-MB by omitting the \f(CWmakeoptions DEBUG-g\fP specification, but if you have
-problems with the system at some later stage, it will be much more difficult to
-find what is causing them.
-.H3 "Building the kernel"
-.X "building the kernel"
-.X "kernel, building"
-Next, change to the build directory and build the kernel:
-.Pn make-kernel
+The next step is to compile all the source files and create a kernel and a set
+of matching \fIkld\fP\/s.  It can take some time, up to an hour on a slow
+machine.  It's also possible to have errors, and unfortunately they are usually
+\fInot\fP self-explanatory.  If the \fImake\fR command fails, it usually signals
+an error in your kernel description that is not obvious enough for \fIconfig\fR
+to catch.  A common one is when you omit an entry from the configuration file
+which is a prerequisite for an entry which is present.  For example, if you have
+SCSI disks (device \f(CWda\fP), you require the \f(CWscbus\fP device as well,
+and if you have just about any kind of Ethernet card, you require the
+\f(CWmiibus\fP device as well:
 .Dx
-# \f(CBcd ../../compile/FREEBIE\fP
-# \f(CBmake depend\fP
-# \f(CBmake all\fP
+device          scbus           # SCSI bus (required)
+device          da              # Direct Access (disks)
+
+device          miibus          # MII bus support
+device          fxp             # Intel EtherExpress PRO/100B (82557, 82558)
 .De
-.Aside
-The \f(CWmake depend\fP is needed even if the directory has just been created:
-apart from creating dependency information, it also creates some files needed
-for the build.
-.End-aside
-This procedure builds a kernel and a set of matching klds.  It can take some
-time, up to an hour on a slow machine.  You can speed up the build by building
-only the kernel (\f(CWmake kernel\fP).  Don't do this the first time you build
-the kernel, but if you find the kernel doesn't boot, and you want to change the
-configuration file and rebuild it from the same sources, you can save some time
-like that.
-.P
-It's also possible to have errors here, and unfortunately they are usually
-\fInot\fP self-explanatory.  If the \fImake\fR command fails, it usually signals
-an error in your kernel description which is not obvious enough for \fIconfig\fR
-to catch it.  Again, look over your configuration, and if you still cannot
-resolve the problem, send mail to \f(CWquestions@FreeBSD.ORG\fR with your kernel
-configuration, and it should be diagnosed very quickly.  A description of how to
-interpret these errors has been in the works for a long time, but currently it's
-still deep magic.
-.P
-.X "kernel, installing"
-.Pn install-kernel
-Finally, install the new kernel:
-.Dx
-# \f(CBmake install\fP
-.De
-.X "/kernel.old"
-This renames the current kernel to \fI/kernel.old\fP and copies the new kernel
-to the root directory as \fI/kernel\fR.
-.P
-FreeBSD 5 will introduce a new hierarchy for the kernel.  The kernel will be
-installed in \fI/boot/kernel/kernel\fP, and the old kernel will be moved to
-\fI/boot/kernel.old/kernel\fP.
+If you leave \f(CWscbus\fP or \f(CWmiibus\fP out of the configuration,
+.Command config
+will not complain, but the kernel link phase will fail with lots of unresolved
+references.
 .P
-.\"XXX make reinstall
+If you can't resolve the problem after comparing your configuration file with
+.File -n GENERIC , 
+send mail to \f(CWquestions@FreeBSD.ORG\fR with your kernel configuration, and
+it should be diagnosed very quickly.  A description of how to interpret these
+errors has been in the works for a long time, but currently it's still deep
+magic.
+.H3 "Rebooting"
 Next, shutdown the system and reboot load the new kernel:
 .Dx
 # \f(CBshutdown -r now\fP
@@ -448,19 +728,23 @@
 panic.  Reset the machine, and when the boot prompt appears, press the space bar
 to interrupt the boot.  Then boot the old kernel:
 .Dx
-Ok \f(CBunload\fP						\fIremove the kernel that the loader has loaded\fP\|
-Ok \f(CBload kernel.old\fP				\fIload the previous kernel (version 4)\fP\|
-Ok \f(CBload /boot/kernel.old/kernel\fP		\fIload the previous kernel (version 5)\fP\|
+Ok \f(CBunload\fP                                \fIremove the kernel that the loader has loaded\fP\/
+Ok \f(CBload /boot/kernel.old/kernel\fP          \fIload the previous kernel\fP\/
 Ok \f(CBboot\fP
 .De
 When reconfiguring a kernel, it is always a good idea to keep on hand a kernel
 that is known to work.  There are two points here:
 .Ls B
 .LI
-If your kernel doesn't boot, you don't want to save it to \fIkernel.old\fP\|
-when you build a new one.  This would overwrite the previous, functional
-kernel.  Instead of performing \f(CWmake install\fP, perform \f(CWmake
-reinstall\fP, which does not rename the old kernel.
+If your kernel doesn't boot, you don't want to save it to \fIkernel.old\fP\/
+when you build a new one.  It's no use, and if the new kernel doesn't boot
+either, you'll be left without a runnable kernel.  In this case, use the
+\f(CWreinstallkernel\fP target mentioned above:
+.Dx
+# \f(CBmake buildkernel KERNCONF=FREEBIE\fP              \fIbuild kernel and klds\fP\/
+# \f(CBmake reinstallkernel KERNCONF=FREEBIE\fP          \fIreinstall kernel and klds\fP\/
+.De
+.SPUP
 .LI
 You could still make a mistake and type \f(CWmake install\fP, throwing away your
 last good kernel.  It's easy enough to end up with a completely unbootable
@@ -468,63 +752,51 @@
 \fIkernel.save\fP, which the installation procedure does not touch.
 .Le
 .P
-.X "/var/log/messages"
-.X "command, dmesg"
-.X "dmesg, command"
 After booting with a good kernel you can check over your configuration file and
-try to build it again.  One helpful resource is the \fI/var/log/messages\fP file
-which records, among other things, all of the kernel messages from every
-successful boot.  Also, the \fIdmesg\fP command will print the kernel messages
-from the current boot.
-.P
-Moving kernels is complicated slightly by the fact that the kernel has the
-\f(CWschg\fP\*F
-.FS
-The \f(CWschg\fP flag makes it impossible to change the file.  This is one of
-the file flags introduced in 4.4BSD.  It is not available on all UNIX-like
-systems.
-.FE
-(immutable) flag set.  You must first ``unlock'' it:
-.Dx
-# \f(CBchflags noschg /kernel\fP
-.De
-And, if you want to ``lock'' your new kernel (or any file for that matter) into
-place so that it cannot be moved or tampered with:
-.Dx
-# \f(CBchflags schg /kernel\fP
-.De
-.sp -1v
+try to build it again.  One helpful resource is the
+.File /var/log/messages
+file which records, among other things, all of the kernel messages from every
+successful boot.  Also, the
+.Command dmesg
+command prints the most recent kernel messages from the current boot.  After
+some time the original messages are overwritten, so the system startup procedure
+saves the messages at boot time in the file
+.File /var/run/dmesg.boot .
+Note that most laptops maintain the previous contents of the kernel message
+buffer when rebooted, so the beginning of the output of
+.Command dmesg
+may relate to an earlier boot.  Check through to the end before jumping to
+conclusions.
 .H2 "Making device nodes"
-.X "device nodes, making"
+.X "device node, making"
 .X "making device nodes"
-.X "/dev/MAKEDEV"
-If you've added any new devices to your kernel, you may have to add device nodes
-to your \fI/dev\fR directory before you can use them.  See page \*[MAKEDEV] for
-further details.  If you're using \fIdevfs\fP, which will be default in version
-5, the kernel creates the device nodes automatically, and you don't need to
-worry about them.
+FreeBSD Release 5 comes with \fIdevfs\fP, the \fIdevice file system\fP.  One
+great advantage of \fIdevfs\fP\/ is that it automatically creates device nodes
+for the hardware it finds, so you no longer need to run the
+.Command -n /dev/MAKEDEV
+script supplied with older releases of FreeBSD.
 .H2 "Kernel loadable modules"
 .Pn kld
-.X "Kernel Loadable Module"
+.X "kernel loadable module"
 .X "kld"
-.X "/modules"
-.X "kldload, command"
-.X "command, kldload"
 As we saw at the beginning of the chapter, you may not have to build a new
 kernel to implement the functionality you want.  Instead, just load it into the
-running kernel with a \fIKernel Loadable Module\fP\| (\fIkld\fP\|).  The
-directory \fI/modules\fP\| contains a number of klds.  To load them, use
-\fIkldload\fP.  For example, if you wanted to load SCO UNIX compatibility, you
-would enter:
+running kernel with a \fIKernel Loadable Module\fP\/ (\fIkld\fP\/).  The
+directory
+.Directory /boot/kernel/modules
+contains a number of klds.  To load them, use
+.Command kldload .
+For example, if you wanted to load SCO UNIX compatibility, you would enter:
 .Dx
 # \f(CBkldload ibcs2\fP
 .De
-This loads the module \fI/modules/ibcs2.ko\fP.  Note that you don't need to
-specify the directory name, nor the \fI.ko\fP\| extension.
+This loads the module
+.File /boot/kernel/modules/ibcs2.ko .
+Note that you don't need to specify the directory name, nor the \fI.ko\fP\/
+extension.
 .P
-.X "kldstat, command"
-.X "command, kldstat"
-To find what modules are loaded, use \fIkldstat\fP\|:
+To find what modules are loaded, use
+.Command kldstat \/:
 .Dx
 # \f(CBkldstat\fP
 Id Refs Address    Size     Name
@@ -534,48 +806,46 @@
  5    1 0xc1771000 e000     linux.ko
  6    1 0xc177f000 bf000    vinum.ko
 .De
-.X "kldunload, command"
-.X "command, kldunload"
-You can also unload some klds, but not all of them.  Use \fIkldunload\fP\| for
-this purpose:
+You can also unload some klds, but not all of them.  Use
+.Command kldunload
+for this purpose:
 .Dx
 # \f(CBkldunload vinum\fP
 .De
-.sp -1v
+You can't unload a kld which has active resources.  In the case of
+.Command vinum ,
+for example, you can only unload it when none of its volumes are mounted.
 .H2 "sysctl"
 .Pn sysctl
-\fIsysctl\fP\| is a relatively new kernel interface which allows access to
-specific variables in the kernel.  Some of these vraiables are read-only: you
+\fIsysctl\fP\/ is a relatively new kernel interface that allows access to
+specific variables in the kernel.  Some of these variables are read-only: you
 can look, but not touch.  Others are changeable.
 .P
-\fIsysctl\fP\| variables are usually referred to simply as \fIsysctls\fP.  Each
-\fIsysctl\fP\| has a name in ``Management Information Base'' (\fIMIB\fP\|) form,
+\fIsysctl\fP\/ variables are usually referred to simply as \fIsysctls\fP.  Each
+\fIsysctl\fP\/ has a name in ``Management Information Base'' (\fIMIB\fP\/) form,
 consisting of a hierarchical arrangement of names separated by periods
 (\f(CW.\fP).  The first component of the name indicates the part of the kernel
 to which it relates.  The following examples give you an idea of how to use the
-\fIsysctl\fP\| program:
+\fIsysctl\fP\/ program:
 .Dx
 $ \f(CBsysctl kern.ostype\fP
 FreeBSD
-$ \f(CBsysctl kern\fP
-\&\fI(lists all sysctls starting with \f(CWkern\fP)\f(CW
-$ \f(CBsysctl -1\fP
-\&\fI(lists all sysctls\fP
-# \f(CBsysctl net.inet.ip.forwarding=1\fP
+$ \f(CBsysctl kern                       \fIlist all sysctls starting with \f(CWkern\fP\f(CW
+$ \f(CBsysctl -a                         \fIlist all sysctls\f(CW
+# \f(CBsysctl net.inet.ip.forwarding=1 \/  \fIturn IP forwarding on\f(CW
 net.inet.ip.forwarding: 0 -> 1
 .De
- Some of the more interesting \fIsysctls\fP\| are:
+ Some of the more interesting \fIsysctls\fP\/ are:
 .Dx
 kern.ostype: FreeBSD
-kern.osrelease: 4.6-RELEASE
-kern.osrevision: 199506
-kern.version: FreeBSD 4.6-RELEASE #0: Mon May 20 17:00:28 CST 2002
-    root@farout.lemis.com:/src/FreeBSD/4.6-RELEASE/src/sys/compile/FREEBIE
-kern.hostname: echunga.lemis.com
-kern.boottime: { sec = 1007165073, usec = 570637 } Sat Dec  1 10:34:33 2001
-kern.bootfile: /kernel
+kern.osrelease: 5.0-RELEASE
+kern.version: FreeBSD 5.0-RELEASE #0: Thu Jan 16 15:03:31 CST 2003
+    grog@freebie.example.org:/usr/src/sys/GENERIC
+kern.hostname: freebie.example.org
+kern.boottime: { sec = 1007165073, usec = 570637 } Fri Jan 17 10:34:33 2003
+kern.bootfile: /boot/kernel/kernel
 kern.init_path: /sbin/init:/sbin/oinit:/sbin/init.bak:/stand/sysinstall
-kern.module_path: /;/boot/;/modules/
+kern.module_path: /boot/kernel;/boot/kernel;/boot/modules;/modules
 kern.coredump: 1
 kern.corefile: /var/tmp/%N.core
 kern.msgbuf: nreach TCP 213.46.243.23:25370 139.130.136.138:25 in via ppp0
@@ -601,22 +871,390 @@
 .Ls B
 .LI
 \f(CWkern.msgbuf\fP shows the contents of the kernel message buffer, which is
-also listed by the \fIdmesg\fP\| program.
+also listed by the \fIdmesg\fP\/ program.
 .LI
 \f(CWkern.corefile\fP specifies a template for the name of the core dump file
 generated when a process fails.  By default the core file ends up in the current
 working directory\[em]whatever that might be.  By specifying an absolute path
 name, you can ensure that any core file will go into a specific directory.  The
 text \f(CW%N\fP is replaced by the name of the program.
+.Le
+.SPUP
+.ne 15v
+.H2 "Living with FreeBSD-CURRENT"
+.Pn current
+.X "FreeBSD-CURRENT, living with"
+.X "living with FreeBSD-CURRENT"
+Keeping up with FreeBSD-CURRENT requires work on your part.  You should be on
+the \f(CWFreeBSD-current@FreeBSD.org\fP mailing list, which you can join via
+majordomo.  See page
+.Sref "\*[support]" \&
+for details of how to use majordomo.
+.H3 "Build kernels with debug symbols"
+.Pn kernel-debugging
+.X "kernel, debugging"
+FreeBSD-CURRENT is not as stable as the released releases.  To prepare yourself
+for possible problems, you should build kernels that include debug symbols.
+The resultant kernel is about 30 MB in size, but it will make debugging with
+\fIddb\fP\/ (the kernel debugger) or \fIgdb\fP\/ much easier.  Even if you don't
+intend to do this yourself, the information will be of great use to anybody you
+may call in to help.  We looked at how to build a debug kernel on page
+.Sref \*[debug-kernel] .
+.H3 "Solving problems in FreeBSD-CURRENT"
+.X "solving problems in FreeBSD-CURRENT"
+.X "FreeBSD-CURRENT, solving problems in"
+You \fIwill\fP\/ run into problems with FreeBSD-CURRENT.  When it happens,
+please first read the mailing list and possibly the mail archives and see if the
+problem has been reported.  If it hasn't, try to investigate the problem
+yourself.  Then send mail to \f(CWFreeBSD-current\fP describing the problem and
+what you have done to solve it.
+.P
+If you experience a panic, please don't just send a message to
+\f(CWFreeBSD-current\fP saying ``My kernel panics when I type \fIfoo\fP\/.''
+Remember that you're asking somebody to use their spare time to look at the
+problem.  Make it easy for them:
+.Ls N
+.LI
+Update to the absolutely latest sources, unless emails have been warning against
+this.
+.LI
+If you have any local patches, back them out.
+.LI
+Recompile, from scratch, your kernel with \fIddb\fP\/ and with complete symbols
+(see above).
+.LI
+Report all details from the panic.  At an absolute minimum, give all information
+from \f(CWshow reg\fP and \f(CWtrace\fP.
+.LI
+Try to dump the system.
+.LI
+If you're successful, follow the procedure discussed in the following section to
+find out something about how the problem occurred.
+.Le
+If you don't do at least this, there isn't much chance that a mail message to
+\f(CWFreeBSD-current\fP will have much effect.
+.H2 "Analyzing kernel crash dumps"
+.Pn dumpanal
+When the kernel panics, and you have dumping enabled, you'll usually see
+something like this on the console:
+.Dx
+Fatal trap 9: general protection fault while in kernel mode
+instruction pointer     = 0x8:0xc01c434b
+stack pointer           = 0x10:0xc99f8d0c
+frame pointer           = 0x10:0xc99f8d28
+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         = 2638 (find)
+interrupt mask          = net tty bio cam
+trap number             = 9
+panic: general protection fault
+
+syncing disks... 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
+giving up on 6 buffers
+Uptime: 17h53m13s
+
+dumping to dev #ad/1, offset 786560
+dump ata0: resetting devices .. done
+.De
+You don't need to write this information down: it is saved in the dump.
+.P
+When you reboot, the system startup scripts find that you have a dump in the
+designated dump device (see above)
+.\" XXX
+and copy it and the current kernel to
+.Directory /var/crash ,
+assuming the directory exists and there's enough space for the dump.  You'll see
+something like this in the directory:
+.Dx
+# \f(CBcd /var/crash\fP
+# \f(CBls -l\fP
+-rw-r--r--  1 root  wheel          3 Dec 29 10:09 bounds
+-rw-r--r--  1 root  wheel    4333000 Dec 29 10:10 kernel.22
+-rw-r--r--  1 root  wheel          5 Sep 17  1999 minfree
+-rw-------  1 root  wheel  268369920 Dec 29 10:09 vmcore.22
+.De
+The important files here are
+.File -n kernel.22 ,
+which contains a copy of the kernel running when the crash occurred, and
+.File -n vmcore.22 ,
+which contains the contents of memory.  The number 22 indicates that the
+sequence number of the dump.  It's possible to have multiple dumps in
+.Directory /var/crash .
+Note that you can waste a lot of space like that.
+.P
+The file
+.File bounds
+contains the number of the next dump (23 in this case), and
+.File minfree
+specifies the minimum amount of free space (in kilobytes) to leave on the file
+system after you've copied the dump.  If this can't be guaranteed,
+.Command savecore
+doesn't save the dump.
+.P
+.Command savecore
+copies the kernel from which you booted.  As we've seen, it typically isn't a
+debug kernel.  In the example above, we installed
+.File /usr/src/sys/i386/conf/FREEBIE/kernel ,
+but the debug version was
+.File /usr/src/sys/i386/conf/FREEBIE/kernel.debug .
+This is the one you need.  The easiest way to access it is to use a symbolic
+link:
+.Dx
+# \f(CBln -s /usr/src/sys/i386/conf/FREEBIE/kernel.debug .\fP
+# \f(CBls -lL\fP
+-rw-r--r--  1 root  wheel          3 Dec 29 10:09 bounds
+-rwxr-xr-x  1 grog  lemis   16796546 Dec 18 14:21 kernel.debug
+-rw-r--r--  1 root  wheel    4333000 Dec 29 10:10 kernel.22
+-rw-r--r--  1 root  wheel          5 Sep 17  1999 minfree
+-rw-------  1 root  wheel  268369920 Dec 29 10:09 vmcore.22
+.De
+As you can see, it's much larger.
+.P
+Next, run
+.Command gdb
+against the kernel and the dump:
+.Dx
+# \f(CBgdb -k kernel.debug vmcore.22\fP
+.De
+The first thing you see is a political message from the Free Software
+Foundation, followed by a repeat of the crash messages, a listing of the current
+instruction (always the same) and a prompt:
+.Dx
+#0  dumpsys () at ../../kern/kern_shutdown.c:473
+473             if (dumping++) {
+(kgdb)
+.De
+Due to the way C,
+.Command gdb
+and FreeBSD work, the real information you're looking for is further down the
+stack.  The first thing you need to do is to find out exactly where it happens.
+Do that with the \fIbacktrace\fP\/ command:
+.Dx
+(kgdb) \f(CBbt\fP
+#0  dumpsys () at ../../kern/kern_shutdown.c:473
+#1  0xc01c88bf in boot (howto=256) at ../../kern/kern_shutdown.c:313
+#2  0xc01c8ca5 in panic (fmt=0xc03a8cac "%s") at ../../kern/kern_shutdown.c:581
+#3  0xc033ab03 in trap_fatal (frame=0xc99f8ccc, eva=0)
+    at ../../i386/i386/trap.c:956
+#4  0xc033a4ba in trap (frame={tf_fs = 16, tf_es = 16, tf_ds = 16,
+      tf_edi = -1069794208, tf_esi = -1069630360, tf_ebp = -912290520,
+      tf_isp = -912290568, tf_ebx = -1069794208, tf_edx = 10, tf_ecx = 10,
+      tf_eax = -1, tf_trapno = 9, tf_err = 0, tf_eip = -1071889589, tf_cs = 8,
+      tf_eflags = 66182, tf_esp = 1024, tf_ss = 6864992})
+    at ../../i386/i386/trap.c:618
+#5  0xc01c434b in malloc (size=1024, type=0xc03c3c60, flags=0)
+    at ../../kern/kern_malloc.c:233
+#6  0xc01f015c in allocbuf (bp=0xc3a6f7cc, size=1024)
+    at ../../kern/vfs_bio.c:2380
+#7  0xc01effa6 in getblk (vp=0xc9642f00, blkno=0, size=1024, slpflag=0,
+    slptimeo=0) at ../../kern/vfs_bio.c:2271
+#8  0xc01eded2 in bread (vp=0xc9642f00, blkno=0, size=1024, cred=0x0,
+    bpp=0xc99f8e3c) at ../../kern/vfs_bio.c:504
+#9  0xc02d0634 in ffs_read (ap=0xc99f8ea0) at ../../ufs/ufs/ufs_readwrite.c:273
+#10 0xc02d734e in ufs_readdir (ap=0xc99f8ef0) at vnode_if.h:334
+#11 0xc02d7cd1 in ufs_vnoperate (ap=0xc99f8ef0)
+    at ../../ufs/ufs/ufs_vnops.c:2382
+#12 0xc01fbc3b in getdirentries (p=0xc9a53ac0, uap=0xc99f8f80)
+    at vnode_if.h:769
+#13 0xc033adb5 in syscall2 (frame={tf_fs = 47, tf_es = 47, tf_ds = 47,
+      tf_edi = 134567680, tf_esi = 134554336, tf_ebp = -1077937404,
+      tf_isp = -912289836, tf_ebx = 672064612, tf_edx = 134554336,
+      tf_ecx = 672137600, tf_eax = 196, tf_trapno = 7, tf_err = 2,
+      tf_eip = 671767876, tf_cs = 31, tf_eflags = 582, tf_esp = -1077937448,
+      tf_ss = 47}) at ../../i386/i386/trap.c:1155
+#14 0xc032b825 in Xint0x80_syscall ()
+#15 0x280a1eee in ?? ()
+#16 0x280a173a in ?? ()
+#17 0x804969e in ?? ()
+#18 0x804b550 in ?? ()
+#19 0x804935d in ?? ()
+(kgdb)
+.De
+The rest of this chapter is only of interest to programmers with a good
+understanding of C.  If you're not a programmer, this is about as far as you can
+go.  Save this information and supply it to whomever you ask for help.  It's
+usually not enough to solve the problem, but it's a good start, and your helper
+will be able to tell you what to do next.
+.H3 "Climbing through the stack"
+The backtrace outputs information about \fIstack frames\fP, which are built when
+a function is called.  They're numbered starting from the most recent frame,
+\f(CW#0\fP, which is seldom the one that interests us.  In general, we've had a
+panic, the most important frame is the function that calls \f(CWpanic\fP:
+.Dx
+#3  0xc033ab03 in trap_fatal (frame=0xc99f8ccc, eva=0)
+    at ../../i386/i386/trap.c:956
+.De
+The information here is:
+.Ls B
+.LI
+\f(CW#3\fP is the frame number.  This is a number allocated by
+.Command gdb .
+You can use it to reference the frame in a number of commands.
+.LI
+\f(CW0xc033ab03\fP is the return address from the call to the next function up
+the stack (\f(CWpanic\fP in this case).
+.LI
+\f(CWtrap_fatal\fP is the name of the function.
 .LI
-\f(CWhw.ata.wc\fP specifies whether ATA disks should perform \fIwrite
-caching\fP.  In this case, they do.  As we saw on page
-.Sref \*[write-cache] ,
-write caching can significantly improve disk performance, but it may cause data
-loss on a crash.
-.P
-This \fIsysctl\fP\| cannot be changed on a running system.  You must set it at
-boot time.  See page
-.Sref \*[boot-sysctls] \&
-for details of how to do that.
+\f(CW(frame=0xc99f8ccc, eva=0)\fP are the parameter values supplied to
+\f(CWtrap_fatal\fP.
+.LI
+\&\f(CW../../i386/i386/trap.c:956\fP gives the name of the source file and the
+line number in the file.  The path names are relative to the kernel build
+directory, so they usually start with \f(CW../../\fP.
 .Le
+In this example, the panic comes from a user process.  Starting at the bottom,
+depending on the processor platform, you may see the user process stack.  You
+can recognize them on an Intel platform by the addresses below the kernel base
+address \f(CW0xc0000000\fP.  On other platforms, the address might be
+different.  In general, you won't get any symbolic information for these frames,
+since the kernel symbol table doesn't include user symbols.
+.P
+Climbing up the stack, you'll find the system call stack frame, in this example
+at frames 14 and 13.  This is where the process involved the kernel.  The stack
+frame above (frame 12) generally shows the name of the system call, in this case
+\f(CWgetdirentries\fP.  To perform its function, \f(CWgetdirentries\fP
+indirectly calls \f(CWffs_read\fP, the function that reads from a UFS file.
+\f(CWffs_read\fP calls \f(CWbread\fP, which reads into the buffer cache.  To do
+so, it allocates a buffer with \f(CWgetblk\fP and \f(CWallocbuf\fP, which calls
+\f(CWmalloc\fP to allocate memory for buffer cache.  The next thing we see is a
+stack frame for \f(CWtrap\fP: something has gone wrong inside \f(CWmalloc\fP.
+\f(CWtrap\fP determines that the trap in unrecoverable and calls
+\f(CWtrap_fatal\fP, which in turn calls \f(CWpanic\fP.  The stack frames above
+show how the system prepares to dump and writes to disk.  They're no longer of
+interest.
+.H3 "Finding out what really happened"
+In general, you start analyzing a panic dump in the stack frame that called
+\f(CWpanic\fP, but in the case of the fatal trap that we have here, the most
+important stack frame is the one below \f(CWtrap\fP, in this case frame 5.
+That's where things went wrong.  Select it with the \f(CWframe\fP command,
+abbreviated to \f(CWf\fP, and list the code with \f(CWlist\fP (or \f(CWl\fP):
+.Dx
+(kgdb) \f(CBf 5\fP
+#5  0xc01c434b in malloc (size=1024, type=0xc03c3c60, flags=0)
+    at ../../kern/kern_malloc.c:233
+233             va = kbp->kb_next;
+(kgdb) \f(CBl\fP
+228                     }
+229                     freep->next = savedlist;
+230                     if (kbp->kb_last == NULL)
+231                             kbp->kb_last = (caddr_t)freep;
+232             }
+233             va = kbp->kb_next;
+234             kbp->kb_next = ((struct freelist *)va)->next;
+235     #ifdef INVARIANTS
+236             freep = (struct freelist *)va;
+237             savedtype = (const char *) freep->type->ks_shortdesc;
+(kgdb)
+.De
+You might want to look at the local (automatic) variables.  Use \f(CWinfo
+local\fP, which you can abbreviate to \f(CWi loc\fP:
+.Dx
+(kgdb) \f(CBi loc\fP
+type = (struct malloc_type *) 0xc03c3c60
+kbp = (struct kmembuckets *) 0xc03ebc68
+kup = (struct kmemusage *) 0x0
+freep = (struct freelist *) 0x0
+indx = 10
+npg = -1071714292
+allocsize = -1069794208
+s = 6864992
+va = 0xffffffff <Address 0xffffffff out of bounds>
+cp = 0x0
+savedlist = 0x0
+ksp = (struct malloc_type *) 0xffffffff
+(kgdb)
+.De
+The line where the problem occurs is 233:
+.Dx
+233             va = kbp->kb_next;
+.De
+Look at the structure \f(CWkbp\fP:
+.Dx
+(kgdb) \f(CBp *kbp\fP
+$2 = {
+  kb_next = 0xffffffff <Address 0xffffffff out of bounds>,
+  kb_last = 0xc1a31000 "",
+  kb_calls = 83299,
+  kb_total = 1164,
+  kb_elmpercl = 4,
+  kb_totalfree = 178,
+  kb_highwat = 20,
+  kb_couldfree = 3812
+}
+.De
+The problem here is that the pointer \f(CWkb_next\fP is set to
+\f(CW0xffffffff\fP.  It should contain a valid address, but as
+.Command gdb
+observes, this isn't not valid.
+.P
+So far we have found that the crash is in \f(CWmalloc\fP, and that it's caused
+by an invalid pointer in an internal data structure.  \f(CWmalloc\fP is a
+function that is used many times a second by all computers.  It's unlikely that
+the bug is in \f(CWmalloc\fP.  In fact, the most likely cause is that a function
+that has used memory allocated by \f(CWmalloc\fP has overwritten its bounds and
+hit \f(CWmalloc\fP's data structures.
+.P
+.ne 5v
+What do we do now?  To quote
+.Command fortune \/:
+.Dx
+        The seven eyes of Ningauble the Wizard floated back to his hood
+as he reported to Fafhrd: "I have seen much, yet cannot explain all.
+The Gray Mouser is exactly twenty-five feet below the deepest cellar in
+the palace of Gilpkerio Kistomerces.  Even though twenty-four parts in
+twenty-five of him are dead, he is alive.
+
+        "Now about Lankhmar.  She's been invaded, her walls breached
+everywhere and desperate fighting is going on in the streets, by a
+fierce host which out-numbers Lankhmar's inhabitants by fifty to one --
+and equipped with all modern weapons.  Yet you can save the city."
+
+        "How?" demanded Fafhrd.
+
+        Ningauble shrugged.  "You're a hero.  You should know."
+                -- Fritz Leiber, from "The Swords of Lankhmar"
+.De
+From here on, you're on your own.  If you get this far, the
+\f(CWFreeBSD-hackers\fP mailing list may be interested in giving suggestions.
+.ig
+Date: Wed, 16 Apr 2003 17:09:39 -0400 (EDT)
+From: John Baldwin <jhb@FreeBSD.org>
+To: John Baldwin <jhb@FreeBSD.org>
+Cc: cvs-all@FreeBSD.org, cvs-src@FreeBSD.org,
+        src-committers@FreeBSD.org
+Subject: RE: cvs commit: src Makefile.inc1
+X-Mailer: XFMail 1.5.4 on FreeBSD  
+ 
+  
+On 16-Apr-2003 John Baldwin wrote:
+> jhb         2003/04/16 14:05:06 PDT
+> 
+>   FreeBSD src repository
+> 
+>   Modified files:
+>     .                    Makefile.inc1 
+>   Log:
+>   Rename KRNLSRCDIR to KERNSRCDIR and allow it to be overridden.  The name
+>   change was to be consistent with other overridable variables such as
+>   KERNCONFDIR and KERNCONF.
+ 
+This allows you to use 'buildkernel' to cross build a kernel and not use
+/usr/src for your sources.  Thus, for example:
+ 
+- Assume full current sources at /usr/src
+- Assume local work tree of kernel sources at /usr/work/jhb/p4/proc
+ 
+% cd /usr/src
+% make TARGET_ARCH=alpha buildworld
+% cd /usr/work/jhb/p4/proc/alpha/conf
+% make LINT
+% cd /usr/src
+% make TARGET_ARCH=alpha NO_MODULES=yes KERNCONF=LINT
+KERNSRCDIR=/usr/work/jhb/p4/proc buildkernel
+ 
+cross builds an Alpha LINT kernel of my process locking branch.
+I used this to cross build Alpha LINT and sparc64 and ia64 GENERIC
+on the jhb_proc branch today.
+..
