Writing Device Drivers

Convert Driver Code to Be 64-Bit Clean

As a first step in converting a device driver to run in a 64-bit kernel, make the driver 64-bit clean by converting to the LP64 data model. For example, make sure that the driver's use of long variables remains consistent between data models.

To enable source code to be both 32-bit and 64-bit safe, the Solaris 2.6 system provides new fixed-width integer types, derived types, constants, and macros in the files <sys/types.h> and <sys/inttypes.h>. The fixed-width types include both signed and unsigned integer types such as int8_t, uint8_t, uint32_t, uint64_t, as well as constants that specify their limits.

Note the following when converting to LP64:

  1. System-derived types, such as size_t, should be used for type declarations whenever possible.

    Using derived types will help make driver code 32-bit and 64-bit safe, since the derived types themselves are safe for both IPL32 and LP64 data models. In addition, it is a good idea to use system-derived types for definitions to allow for future change.

  2. Fixed-width types, such as uint32_t, should be used where appropriate to clearly specify type declarations.

    Fixed-width integer types are useful for representing explicit sizes of binary data structures or hardware registers, while fundamental C language data types, such as int, can still be used for loop counters or file descriptors. In particular, make sure that use of variables of type long remains accurate. As a long is 64 bits in LP64, change variables that represent 32-bit data and that are currently defined as long to fixed-width 32-bit types, such as uint32_t.

  3. The new derived types uintptr_t or intptr_t should be used as the integral type for pointers.

    Pointers are 64 bits in size in the Solaris 64-bit environment. Although pointers could be recast to long, the new derived system types should be used instead, particularly when pointers are used to do address arithmetic or alignment. In addition, check for code that assumes that int and pointer variables are the same size, and use uintptr_t instead of int for variables that are cast to pointers. For example, change:

    		char *p;
     	p = (char *)((int)p & PAGEOFFSET);

    to:

    		p = (char *)((uintptr_t)p & PAGEOFFSET);

The new fixed width data types in <sys/inttypes.h> are included in <sys/ddi.h>.


Caution - Caution -

Caution: Do not ignore compilation or lint warnings during conversion for LP64, because even those that were safe to ignore previously in the ILP32 environment may now indicate a more serious problem.


Useful Tools to Check Data Model Conversion

Running driver code through the Sun WorkShop Compiler C 4.2 lint utility can help find problems with data models. This version of lint provides warnings about potential 64-bit problems. It prints the line number of the problem code and a warning message describing the problem, indicates whether a pointer was involved, and provides information about the size of the data types.

To use lint(1B) to check for data model conversion problems, use the -errchk=longptr64 option.