10    Building a Kernel Module

This chapter discusses how to build a kernel module that you can statically link or dynamically load into the kernel:

10.1    Building a Kernel Module

A kernel module has a file extension of .mod. It must contain a module_name_configure routine and a module_name_attributes table, as described in Chapter 2.

Before you can statically link or dynamically load a kernel module, you must build it. To build a kernel module, perform the following steps:

  1. Create a directory to contain the source files

  2. Copy the source files

  3. Create a files file fragment

  4. Create a BINARY.list file

  5. Create a sysconfigtab file fragment

  6. Create a Makefile

  7. Build the kernel module

The following sections discuss each of these steps.

10.1.1    Step 1: Create a Directory to Contain the Source Files

Use the mkdir command to create a directory to contain the source files for the kernel module:

# mkdir /usr/sys/ExampMod

The directory path must start with /usr/sys. In this example, you create a directory called /usr/sys/ExampMod to contain the files for the example kernel module. You perform the work at the superuser prompt.

When you create your directory, replace ExampMod with a directory that reflects a specific name for your organization or company.

10.1.2    Step 2: Copy the Source Files

Use the cp command to copy the source and header files to the directory that you created in Section 10.1.1:

# cd /usr/sys/ExampMod 
# cp /usr/sys/mydevelopment/example.c . 
# cp /usr/sys/mydevelopment/example_util.c 
# cp /usr/sys/mydevelopment/example.h . 
 
 

The /usr/sys/mydevelopment directory is where you initially created the source files (example.c, example_util.c, and example.h).

10.1.3    Step 3: Create a files File Fragment

The files file fragment describes the source files (.c), the kernel module name, and characteristics.

Use an editor such as vi to create a files file fragment in the directory that you created in Section 10.1.1:

# vi /usr/sys/ExampMod/files

The basic syntax for the files file fragment is as follows:

MODULE/STATIC/module_name  standard|optional[options] Binary  [1]
path/file_name.c module module_name flags[flag_list]  [2]

  1. Declares a kernel module.

    The keywords MODULE/STATIC specify that you can statically link or dynamically load the module into the kernel.

    The keyword standard indicates that the module will be included in every kernel.

    The keyword optional indicates that the module will be included in the kernel only if the options are present in the kernel configuration file. The keyword options can be anything such as the module name, the bus name, or the platform name.

    The keyword Binary causes the sourceconfig program to generate the build rules in the BINARY Makefile. When you run this Makefile, it builds the kernel module and places it in the /usr/sys/BINARY directory. [Return to example]

  2. Includes a source file in the specified kernel module.

    The keyword path is the pathname that you created in Section 10.1.1. The build process adds /usr/sys/ to the front of the path by default. Therefore, you do not include /usr/sys/ in your path.

    The keyword module_name is the name of the kernel module that you are building.

    The most common keyword is flags, followed by one or more compiler flags. For more information on valid compiler flags, see cc(1) . [Return to example]

The following example shows the files file fragment for the example kernel module using the keyword standard:

# This is the files file fragment for the example kernel module
# using the keyword standard.
#
MODULE/STATIC/example standard Binary 
ExampMod/example.c module example 
ExampMod/example_util.c module example 
 
 

This fragment instructs the build facility to compile the example.c and example_util.c source files and put them in the example.mod module.

The following example shows the files file fragment for the example kernel module using the keyword optional:

# This is the files file fragment for the example kernel module
# using the keyword optional.
#
MODULE/STATIC/example optional example Binary 
ExampMod/example.c module example flags -g3
ExampMod/example_util.c module example flags -g3
 
 

This instructs the build facility to compile the example.c and example_util.c source files using the -g3 compiler flag and put the source files in the example.mod module. The module will be linked in the kernel only if the option example is in the configuration file.

10.1.4    Step 4: Create a BINARY.list File

The BINARY.list file contains the location of products that are not part of the standard operating system. Use an editor such as vi to edit or create a BINARY.list file in the /usr/sys/conf directory:

# cd /usr/sys/conf 
# vi BINARY.list

The following example shows the typical contents of the BINARY.list file that you create:

/usr/sys/ExampMod:

The file contains the directory path that you created in Section 10.1.1. You must follow the path name with a colon (:), as shown in the example.

10.1.5    Step 5: Create the sysconfigtab File Fragment

The sysconfigtab file fragment is optional but most device drivers require one. It contains the module name and attributes. Use an editor such as vi to create a sysconfigtab file fragment in the directory that you created in Section 10.1.1:

# cd /usr/sys/ExampMod 
# vi sysconfigtab

The syntax for a sysconfigtab file entry follows the stanza(4) syntax:

#The following illustrates a sysconfigtab entry.  [1]
module_name:  [2]
            Attribute1_name = Attribute1_value  [3]
            Attribute2_name = Attribute2_value
            Attribute3_name = Attribute3_value
    .
    .
    .

  1. Includes comments at the beginning or at the end of a kernel module sysconfigtab entry. Comments are not allowed within the body of the sysconfigtab entry. [Return to example]

  2. Specifies the name of the kernel module, followed by a colon (:). Typically, each module contains a separate sysconfigtab file entry. [Return to example]

  3. Specifies an attribute and its value. A valid sysconfigtab entry consists of an attribute name, an equal sign (=), and one or more values. Put each attribute name and value pair on a separate line. [Return to example]

In our example, the sysconfigtab file fragment for the example kernel module would be as follows:

# The following illustrates a sysconfigtab entry  
# in the sysconfigtab file fragment for the example driver.
example: [1]
      [2]PCI_Option =  PCI_SE_Rev - 0x210, Vendor_Id - 0x1002, Device_Id - 0x4354, 
                       Rev - 0, Base - 0, Sub - 0, Pif - 0 Sub_Vid - 0, Sub_Did - 0, 
                       Vid_Mo_Flag - 1, Did_Mo_Flag - 1, Rev_Mo_Flag - 0, Base_Mo_Flag - 0, 
                       Sub_Mo_Flag - 0, Pif_Mo_Flag - 0, Sub_Vid_Mo_Flag - 0, 
                       Sub_Did_Mo_Flag - 0, Driver_Name - example, Type - C, Adpt_Config - N
        EXAMPLE_Developer_Debug = 1     [3]
 
 

  1. Indicates that the attributes that follow belong to the example module. [Return to example]

  2. Initializes the PCI adapter information attribute to allow identification of the example PCI adapters by the driver framework code. You must insert an attribute's value on one line which may wrap to subsequent lines. However, you cannot embed newline characters. [Return to example]

  3. Initializes the EXAMPLE_Developer_Debug attribute to 1, which turns on debugging messages. [Return to example]

You can specify any configurable attributes in /etc/sysconfigtab and declare the module's attributes in the module_name_attribute table in one of the module's source files.

Although not all attributes in the module's attribute table need to appear in the sysconfigtab file fragment, all attributes that appear in the sysconfigtab file fragment must be in the module's attribute table.

A module can have no attributes or it can have attributes that do not need to be modified. In those cases, the sysconfigtab file fragment is optional. If you create a file fragment, it only contains the module name followed by a colon (:).

For more information, see sysconfigtab(4).

10.1.6    Step 6: Create a Makefile

To create a Makefile, run the sourceconfig program from the /usr/sys/conf directory :

# cd /usr/sys/conf 
# ./sourceconfig BINARY [1]

  1. Invoke the sourceconfig program followed by the BINARY configuration file name. This generates a new Makefile in the /usr/sys/BINARY directory. This Makefile contains the information to compile the standard Tru64 UNIX modules as well as the kernel module or modules that are defined in the BINARY.list file. [Return to example]

10.1.7    Step 7: Build the Kernel Module

Run the make program from the /usr/sys/BINARY directory to create your kernel module:

# cd /usr/sys/BINARY 
# make example.mod [1]

  1. Invoke the make program followed by the name of your kernel module plus the .mod extension. This step creates the kernel module in the /usr/sys/BINARY directory. In this example, example.mod is the kernel module for the example module, created in the /usr/sys/BINARY directory. This step also creates a link from the /usr/sys/BINARY directory to the directory that you created in Section 10.1.1.

    Invoke the make program for each module that you want to compile. The appropriate links are created as described in the previous paragraph. [Return to example]

You now have a kernel module that can be statically linked or dynamically loaded into the kernel.

10.2    Adding Your Module's Attributes

The sysconfigdb utility appends the sysconfigtab file fragment to the existing /etc/sysconfigtab file. Using sysconfigdb ensures that users never manually edit the etc/sysconfigtab file.

If you have a sysconfigtab file fragment, run the sysconfigdb utility. In this example, the sysconfigdb utility is invoked with the following flags:

# sysconfigdb -a -f /usr/sys/ExampMod/sysconfigtab example 
 

For more information, see sysconfigdb(8).

10.3    Statically Link a Kernel Module into a /vmunix Kernel

To statically link a kernel module into a /vmunix kernel, follow the steps in Section 10.1 to build your kernel module. After your kernel module is created, follow the steps outlined in this section.

10.3.1    Step 1: Create a Kernel Build Directory

To test your kernel module, create a new kernel build directory by running the doconfig program and specifying a new name for the target configuration file. This example uses the name CONRADtest.

  1. Run the doconfig program from the /usr/sys/conf directory:

    # cd /usr/sys/conf 
    # doconfig
    

  2. Enter the new name for the target configuration at the following prompt:

    *** KERNEL CONFIGURATION AND BUILD PROCEDURE *** 
    Enter a name for the kernel configuration file. [CONRAD] CONRADtest
    

    By specifing a new target configuration file name, the pre-existing configuration (CONRAD in this example) remains intact so that a working configuration is always available.

  3. When you are prompted for kernel options, select any options or select none. In response to the following prompt, indicate that you do not want to edit the target configuration file:

    Do you want to edit the configuration file? (y/n) [n]: n
    

    The doconfig program will now proceed to build a new kernel in the /usr/sys/CONRADtest directory.

10.3.2    Step 2: Create a NAME.list File

To extend the basic kernel to include your new module, you need to create a NAME.list file where NAME is the name of the new kernel build directory. In the example, this file is called CONRADtest.list because the build directory name we entered in Section 10.3.1 was CONRADtest.

Use an editor such as vi to edit or create a CONRADtest.list file in the /usr/sys/conf directory:

# cd /usr/sys/conf
# vi CONRADtest.list

The CONRADtest.list file contains the pathname of the directory where the module files are located. This is the same directory which was created in Section 10.1.1. For our example, this is:

/usr/sys/ExampMod:

You must follow the pathname with a colon (:), as shown in the example. It is important that there is only one CONRADtest.list file can exist for the CONRADtest configuration. This file must specify all additional products and modules to be linked into the kernel. In this example, we only have one module. If you have more than one module or product to test, add each pathname on its own line, followed by a colon.

10.3.3    Step 3: Run the doconfig Program

The doconfig program takes the configuration information from the /usr/sys/conf/CONRADtest file along with the information from the /usr/sys/conf/CONRADtest.list file and produce a kernel. The resulting kernel will have the new module linked into it.

Run the doconfig program from the /usr/sys/conf directory. Use the new kernel configuration name that you created in Section 10.3.1:

# cd /usr/sys/conf 
# doconfig -c CONRADtest

If you specified the keyword standard in the files file fragment, take the defaults for all prompts. If you specified the keyword optional in the files file fragment, answer yes when you are prompted to edit the configuration file. Doing so opens the configuration file. Add the following at the end of the file:

config_driver example

Replace example with the name of your module to include it in the linked kernel.

The doconfig program will now proceed to build a new kernel in the /usr/sys/CONRADtest directory.

10.3.4    Step 4: Copy the New Kernel to the Root Directory

Copy the new kernel from the kernel build directory to the root directory. We strongly recommend that you leave the existing and working /vmunix in the root directory and that you do not overwrite it. Rather, assign a new name to the new kernel as shown in this example:

# cp /usr/sys/CONRADtest/vmunix /vmunix.example

The kernel name vmunix.example illustrates that the new kernel includes the example module.

10.3.5    Step 5: Shut Down and Boot the System

To test the new module, you must shut down and reboot the system with the new kernel. Make sure to specify the name of your new kernel when booting:

# shutdown -h now 
>>> boot -fi "vmunix.example"

The kernel module is now part of this new kernel and can be tested with the appropriate utilities.

10.4    Dynamically Load a Kernel Module

To dynamically load a kernel module into a /vmunix kernel, follow the steps in Section 10.1 to build your kernel module. After your kernel module is created, follow the steps outlined in this section.

10.4.1    Step 1: Create the Appropriate Links

From the /var/subsys directory, create the following symbolic links:

# cd /var/subsys 
# ln -s /usr/sys/BINARY/example.mod example.mod [1]
# ln -s /subsys/device.mth example.mth [2]

  1. Create a symbolic link to the kernel module example.mod in the /usr/sys/BINARY directory. The symbolic link has the same name as the kernel module example.mod. Replace example.mod with the name of your kernel module. [Return to example]

  2. Create a symbolic link to the kernel method file. The device.mth should already exist in the /subsys directory. The symbolic link has the same name as the kernel module but with a .mth extension, example.mth. Replace example with the name of your kernel module. [Return to example]

10.4.2    Step 2: Load the Kernel Module

Use the sysconfig utility with the -c option to load and configure the kernel module:

# sysconfig -c example

Replace example with the name of your kernel module. The -c option dynamically loads the kernel module and configures it into the running kernel. If your module is a device driver, its device special files are also created at this time.

10.5    Changing Attribute Values at Run Time

Users, especially system administrators, may sometimes want to change attributes. You may also need to change an attribute value during kernel module development to test features of the kernel module. The sysconfig program allows you and your users to reconfigure a kernel module with new attribute values.

You can modify attributes at run time whether the kernel module was statically linked or dynamically loaded into the kernel.

For example, the example kernel module from Section 10.1.5 initializes the EXAMPLE_Developer_Debug attribute to 1 by default, which turns debugging messages on. To turn the messages off, call the sysconfig program as follows:

# sysconfig -r example EXAMPLE_Developer_Debug=0

The -r flag directs the example module to be reconfigured with the new EXAMPLE_Developer_Debug attribute value of 0.

Not all attributes can be changed with sysconfig. To allow an attribute to change at run time, you must assign the CFG_OP_RECONFIGURE constant to the operation field of the attribute's cfg_subsys_attr_t data structure. The sysconfig program returns an error if you try to change an attribute that does not have this operation value.

The sysconfig program calls the module framework to change the value stored in memory. The module framework then calls the kernel module's configure request code to perform any other operations that are required to reconfigure the module.