Writing Device Drivers

Macros

adb(1) and kadb(1M) support macros. adb(1) macros are in /usr/lib/adb and /usr/platform/`uname -i`/lib/adb for 32-bit programs and in /usr/lib/adb/sparcv9 and /usr/platform/`uname -i`/lib/adb/sparcv9 for 64-bit programs. kadb(1M) macros are builtin and can be displayed with $M. Most of the existing macros are for private kernel structures. New macros for adb can be created with adbgen(1M).

Macros are used in the form:

	[ address ] $<macroname

threadlist is a useful macro that displays the stacks of all the threads in the system. Because this macro does not take an address and can generate excessive output, be ready to use Control-S and Control-Q to start or stop if necessary--this is another good reason to use a tip window. Control-C can be used to abort the listing.

kadb[0]: $<threadlist

                ============== thread_id        f0244020
p0:
p0:             process args=   sched
t0:
t0:             lwp             proc            wchan
                f02a3e78        f02a8078        0
t0+0x34:        sp              pc
                f0243af0        sched+0x4e0
?(?) + 0
main(0x0,0xf02b7e20,0xf02a800c,0x0,0x6e,0x0)
afsrbuf(?) + 1b8
exitto(0xf0040000,0xf02a0f58,0x3c,0xf02d3c40,0xfbd7d668,0x0)

                ============== thread_id        fbe01ea0
p0:
p0:             process args=   sched
0xfbe01ea0:     lwp             proc            wchan
                0               f02a8078        0
0xfbe01ed4:     sp              pc
                fbe1fe68        debug_enter+0xb0
?(?) + 0
abort_sequence_enter(0x0,0x740000,0xc4,0x0,0x0,0x40000e7)
zsa_xsint(0xf5dd9000,0x80,0xf5dd906c,0x44,0xff0113,0x0) + 244
zs_high_intr(0xf5dd9000) + 204
_level1(0x0) + 13bc
idle(0xf02a0fac,0x0,0xf02a8078,0xf02a8078,0xf004684c,0x4400ae1) + 50

                ============== thread_id        fbe22ea0
p0:
p0:             process args=   sched
0xfbe22ea0:     lwp             proc            wchan
                0               f02a8078        f5caf024
0xfbe22ed4:     sp              pc
                fbe22d80        cv_wait+0x64
?(?) + 0
cv_wait(0xf5caf024,0xf5caf010,0xffdf1175,0x6ea7e,0xf5caf030,0x40000000)
callout_thread(0xf5caf010,0xf5caf024,0xf02a8078,0xf02a8078,0x1000,0x4400ae5)+38
...

Another useful macro is thread. Given a thread ID, this macro prints the corresponding thread structure. This can be used to look at a certain thread found with the threadlist macro, to look at the owner of a mutex, or to look at the current thread.

kadb[0]: <g7$<thread
0xfbe01ea0:0xfbe01ea0:     link            stk             startpc         bound
                0               fbe01e40        f0076d40        f02a0fac
0xfbe01eb0:     affcnt          bind_cpu        flag            procflag
                1               -1              8               0
0xfbe01eb8:     schedflag       preempt         preempt_lk      state
                3               1               0               4
0xfbe01ec0:     pri             epri            pc              sp
                -1              0               f005bdf8        fbe1fe68
0xfbe01ecc:     wchan0          wchan           sobj_ops        cid
                0               0               0               0
0xfbe01edc:     clfuncs         cldata          ctx             lofault
                f02aeed8        0               0               0
0xfbe01eec:     onfault         nofault         swap            lock
                0               0               fbe01000        ff
0xfbe01efa:     delay_cv        cpu             intr            did
                0               f02a0fac        0               1
0xfbe01f08:     tnf_tpdp        tid             alarmid
                f5a75c80        0               0               realitimer
0xfbe01f14:     interval.sec    interval.usec   value.sec       value.usec
                0               0               0               0
0xfbe01f24:     itimerid        sigqueue        sig
                0               0               0               0
0xfbe01f34:     hold                            forw            back
                0               0               0               0
0xfbe01f44:     lwp             procp           next            prev
                0               f02a8078        fbe04ea0        f0244020
0xfbe01f58:     trace           why     what    dslot           pollstate
                0               0       0       0               0
0xfbe01f68:     cred            lbolt           sysnum          pctcpu
                0               0               0               0
0xfbe01f88:     lockp           oldspl          pre_sys         disp_queue
                f02a1014        e0              0               f02a0ff0
 ...

Note -

No type information is kept in the kernel, so using a macro on an inappropriate object results in garbage output.


Macros do not necessarily output all the fields of the structures, nor is the output necessarily in the order given in the structure definition. Occasionally, memory may need to be dumped for certain structures and then matched with the structure definition in the kernel header files.


Caution - Caution -

Drivers should never reference header files and structures not listed in Section 9S of the Solaris 2.7 Reference Manual. However, examining non-DDI-compliant structures (such as thread structures) can be useful in debugging drivers.