mload(4) mload(4) NAME mload - dynamically loadable kernel modules DESCRIPTION IRIX supports dynamic loading and unloading of modules into a running kernel. Kernel modules can be registered and then loaded automatically by the kernel when the corresponding device is opened, or they can be loaded manually. Similarly, dynamically loaded modules can be unloaded automatically or manually if the module includes an unload entry point. A loadable kernel module can be a character, block or streams device driver, a streams module, a library module or the idbg.o module. Module Configuration Each loadable module should contain the string: char *prefixmversion = M_VERSION; M_VERSION is defined in the mload.h header file, which should be included by the loadable module. A number of cc flags must be defined correctly when compiling loadable modules for Irix. To ensure that you get the correct flags, use the sample makefile in /var/sysgen/Makefile.kernloadio from the eoe.hdr.lib subsystem. Instructions for using the makefile are at the beginning of the Makefile.kernloadio file. A loadable module must not be dependent on any loadable module, other than a library module. In order to load a module comprised of multiple object files, the object files should be linked together into a single object file, using the following ld options: -G0 -r -d Loading a Dynamically Loadable Kernel Module Either lboot or the ml command can be used to load, register, unload, unregister, and list loadable kernel modules. The lboot command parses module type, prefix and major number information from the module's master file found in the /var/sysgen/master.d directory. The loadable object file is expected to be found in the /var/sysgen/boot directory. The ml command also provides a means of loading, registering and unloading loadable modules, without the need for creating a master file or reconfiguring the kernel. Load When a module is loaded, the object file's header is read; memory is allocated for the module's text, data and bss; the module's text and data are read; the module's text and data are relocated and unresolved references into the kernel are resolved; a symbol table is created for the module; the module is added to the appropriate kernel switch table; and the module's init routine is called. A module is loaded using the following ml command: ml ld [-v] -[cbBfmi] module.o -p prefix [-s major major ...] [-a modname] If a module is loaded successfully, an id number is returned which can be used to unload the module. A module can also be loaded using lboot: lboot -L master Register The register command is used to register a module for loading when its corresponding device is opened. When a module is registered, a stub routine is entered into the appropriate kernel switch table. When the corresponding device is opened, the module is actually loaded. A module is registered using the following ml command: ml reg [-v] -[cbBfmi] module.o -p prefix [-s major major ...] [-a modname] [-t autounload_delay] If a module is registered successfully, an id number is returned which can be used to unregister the module. A module can also be registered using lboot: lboot -R master Unload A module can be unloaded only if it provides an unload entry point. A module is unloaded using: ml unld id [id id ...] or lboot -U id [id id ...] Unregister A module can be unregistered using: ml unreg id [id id ...] or lboot -W id [id id ...] List All loaded and/or registered modules can be listed using: ml list [-rlb] or lboot -V Master File Configuration If a dynamically loadable module has an associated master file, the master file should include a d in Field 1. The d flag indicates to lboot that the module is a dynamically loadable kernel module. If the d flag is present lboot will parse the module's master file, but will not fill in the entry in the corresponding kernel switch table for the module. All global data defined in the master file will be included in the generated master.c file. The kernel should be configured with master files that contain the d option for each module that will be a dynamically loadable module, if lboot will be used to load, register, unload, unregister or autoregister the module. If the ml(1M) command will be used, then it is not necessary to create a master file for the module. Auto Registration Loadable modules can be registered by lboot automatically at system startup when autoconfig is run. In order for a module to be auto- registered, its master file should contain an R in Field 1, in addition to d, which indicates that the module is loadable. When lboot runs at system startup, it registers each module that contains an R in its master file. Modules which specify a particular major number are registered before modules which pick a major number dynamically. If an rc2 script is added, which registers or loads dynamically loadable modules, it should be run after the autoconfig rc2 script is run. For more detailed information, see the lboot(1M), ml(1M), and master(4) reference pages. Auto Unload All registered modules that include an unload routine are automatically unloaded after last close, unless they have been configured not to. Modules are unloaded five minutes after last close by default. The default auto-unload delay can be changed by using systune to change the module_unld_delay variable. For more information about systune, see the systune(1M) reference page. A particular module can be configured with a specific auto-unload delay by using the ml command. A module can be configured to not be auto-unloaded by either placing an N in the flags field of its master.d file, if it is registered using lboot, or by using ml to register the module and using the -t option. Kernel Configuration A kernel which supports loadable modules, should be configured so that the kernel switch tables generated by lboot(1M) contain "extra" entries for the loadable modules. Extra entries are generated by lboot based on the values of the following kernel tuneable parameters: * name default minimum maximum bdevsw_extra 21 1 254 cdevsw_extra 23 3 254 fmodsw_extra 20 0 vfssw_extra 5 0 These tuneable parameters are found in the kernel /var/sysgen/mtune/kernel file and are set to the defaults listed above. For more information about changing tuneable parameters, see the mtune(4) and systune(1M) reference pages. Module Entry Points Loadable device drivers should conform to the SVR4 DDI/DKI standard. In addition to the entry points specified by the DDI/DKI standard, if a loadable module is to be unloaded, the module needs to contain an unload entry point: int prefixunload (void) An unload routine should be treated as an interrupt routine and should not call any routines that would cause it to sleep, such as: biowait(), sleep(), psema() or delay(). An unload routine should free any resources allocated by the driver, including freeing interrupt vectors and allocated memory and return 0. Module Initialization After a module is loaded, linked into the kernel and sanity checking is done, the modules' initialization routines, prefixinit(), prefixedtinit() and prefixstart() are called, if they exist. For more information on these routines, refer to the SVR4 DDI/DKI Reference Manual and the IRIX Device Driver Programmer's Guide. Edt Type Drivers For drivers that have an edtinit entry point, which get passed a pointer to an edt structure, lboot must be used to load the driver. A vector line should be added to the system file for the driver, as it would for any driver. When the module is loaded, using lboot, lboot parses the vector line from the system file to create an edt structure which is passed through the kernel and to the driver's edtinit routine. For more information, see the system(4) reference page. Library Modules A library module is a loadable module which contains a collection of functions and data that other loaded modules can link against. A library module can be loaded using the following ml command: ml ld [-v] -l library.o A library module must be loaded before other modules that link against it are loaded. Library modules can not be unloaded, registered or unregistered. Only regular object files are supported as loadable library modules. The idbg.o Module The idbg.o module can be dynamically loaded into a running kernel, so that the kernel print utility, idbg(1M), can be used without reconfiguring and rebooting a new kernel. The idbg.o module can be dynamically loaded using the ml command: ml ld -i /var/sysgen/boot/idbg.o -p idbg The idbg.o module can also be unloaded. Other idbg modules, such as xfsidbg.o, xlvidbg.o, mloadidbg.o, and so on, can be loaded after idbg.o is loaded. For example: ml ld -i /var/sysgen/boot/xfsidbg.o -p xfsidbg.o For more information, see the idbg(1M) reference page. Loadable Modules and Hardware Inventory Many device drivers add to the hardware inventory in their init or edtinit routines. If a driver is a dynamically loadable driver and is auto-registered, it will not show up in the hardware inventory until the driver has been loaded on the first open of the corresponding device. If a clean install or a diskless install is done, a /dev entry will not get created by MAKEDEV for such a driver since it doesn't appear in the hardware inventory. If such a situation arises, the D master.d flag can be used to indicate that the driver should be loaded, then unloaded by autoconfig. If the R master.d flag, which indicates that the driver should be auto-registered, is also used, then the driver will be auto- registered as usual. A startup script can then be added that will run MAKEDEV after autoconfig, if necessary. For an example, see the /etc/init.d/chkdev startup script. Kernel Runtime Symbol Table A runtime symbol table which contains kernel routines and global data that modules can link against is created from the ELF symbol information in the kernel that was booted. The runtime symbol table is created automatically by the kernel from the file indicated by the kernname environment variable, which is set by sash to the name of the file that was booted. The symbol table is loaded with a default auto-unload timeout of five minutes, after which the symbol table is automatically unloaded. The symbol table is automatically reloaded when needed to resolve symbols (for example when a new or registered module is loaded). The kernel runtime symbol table can also be loaded manually, using the ml command: ml ld -r /unix Or unloaded manually: ml unld id Note that only one kernel runtime symbol table can exist at one time. Auto-loading and unloading of the kernel runtime symbol table can be disabled using the mload_auto_rtsyms systune variable. For more information about tuneable variables, see the systune(1M) reference page. Debugging Loadable Modules symmon(1M) supports debugging of loadable modules. symmon commands that do a symbol table lookup, such as: brk, lkup, lkaddr, hx and nm, also search the symbol tables created for loadable modules. The msyms command can also be used to list the symbols for a particular loaded module: msyms id The mlist command can be used to list all of the modules that are currently loaded and/or registered. For more information, see the symmon(1M) reference page. Load/Register Failures If a registered module fails to load, it is suggested that the module be unregistered and then loaded using ml ld or lboot -L, in order to get a more detailed error message about the failure. All of the error codes, including a description of each, are listed in the mload.h header file, found in the /usr/include/sys directory. The kernel will fail to load or register a module for any of the following reasons: 1. If autoconfig is not run at system startup, none of the dynamically loadable modules will be registered or loaded. 2. If autoconfig fails for some reason, before it has processed the dynamically loadable module master.d files, the modules will not be registered or loaded. 3. The major number specified either in the master file, or by the ml command, is already in use. 4. The object file is not compiled with the correct options, such as -G0 and -jalr. 5. The module is an "old style" driver, with either xxxdevflag set to D_OLD, or no xxxdevflag exists in the driver. 6. A corrupted object file could cause "invalid JMPADDR" errors. 7. Not all of the module's symbols were resolved by the kernel. 8. The device switch table is full and has no more room to add a loadable driver. 9. Required entry points for the particular type of module are not found in the object file, such as xxxopen for a character device driver. 10. All major numbers are in use. 11. An old sash is used to boot the kernel, which does not set the kernname environment variable, which indicates the on-disk kernel image to load the runtime symbol table from (for example, /unix). This will cause all loadable modules to fail to load or be registered. To find out what the kernname environment variable is set to, use the nvram(1M) command: nvram kernname 12. The runtime symbol table can not be loaded from the file indicated by the kernname environment variable, because the file does not exist, the file is not the same as the running kernel or the kernel was bootp'ed from another machine. EXAMPLE 1 The following example lists the steps necessary to build a kernel and load a character device driver, called dlkm, using the lboot command: 1. Add d to the dlkm master file: *FLAG PREFIX SOFT #DEV DEPENDENCIES cd dlkm 38 2 2. Make sure that the cdevsw_extra kernel tuneable parameter allows for extra entries in the cdevsw table, the default setting in /var/sysgen/mtune/kernel is: cdevsw_extra 23 3 254 The systune(1M) command also lists the current values of all of the tuneable parameters. If the kernel is not configured to allow extra entries in the cdevsw table, use the systune command to change the cdevsw_extra parameter: > systune -i systune-> cdevsw_extra 3 systune-> quit > 3. Build a new kernel and boot the target system with the new kernel. 4. Compile the dlkm.c driver. It should be noted that linking either 64bit or 32bit objects the "-non_shared" flag is not needed. For 32-bit modules: cc -non_shared -elf -G0 -r -d -jalr -c dlkm.c For 64-bit modules: cc -non_shared -elf -G 0 -jalr -c dlkm.c 5. Copy dlkm.o to /var/sysgen/boot. 6. Load the driver into the kernel: lboot -L dlkm 7. List the currently loaded modules to verify that the module was loaded: lboot -V EXAMPLE 2 The following example lists the steps necessary to load a character device driver, called dlkm, using the ml command: 1. Follow step 2 from example 1. 2. Follow step 4 from example 1. 3. Load the driver into the kernel: ml ld -c dlkm.o -p dlkm -s 38 If a major number is not specified, the first free major number in the MAJOR table is used. If the load was successful, an id number is returned, which can be used to unload the driver. 4. List the currently loaded modules to verify that the module was loaded: ml list CAVEATS 1. Loadable modules must not have any dependencies on loadable modules, other than library modules. When a module is loaded, it is linked against the kernel symbol table and any loaded library modules' symbol tables, but it is not linked against other modules' symbol tables. 2. Only character, block and streams device drivers, streams modules and library modules are supported as loadable modules at this time. 3. Old style drivers (devflag set to D_OLD) are not loadable. 4. Kernel profiling does not support loadable modules. 5. Memory allocated may be in either K0SEG or in K2SEG. If the module is loaded into K2SEG static buffers are not necessarily in physically contiguous memory. Also, depending on machine configuration, K2SEG addresses may map to high physical memory addresses, in which case, PHYS_TO_K0 and PHYS_TO_K1 macros will not work. SEE ALSO cc(1), lboot(1M), ld(1), ml(1M), symmon(1M), systune(1M), master(4), mtune(4). IRIX Device Driver Programmer's Guide Page 9