diff --git a/sys/kern/kern_lkm.c b/sys/kern/kern_lkm.c index e52de1309abd..04551e1000ff 100644 --- a/sys/kern/kern_lkm.c +++ b/sys/kern/kern_lkm.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_lkm.c,v 1.44 1998/08/04 04:03:12 perry Exp $ */ +/* $NetBSD: kern_lkm.c,v 1.45 1999/01/13 23:06:28 sommerfe Exp $ */ /* * Copyright (c) 1994 Christopher G. Demetriou @@ -40,6 +40,7 @@ * with, but "not right now." -- cgd */ +#include "opt_ddb.h" #include "opt_uvm.h" #include @@ -59,6 +60,10 @@ #include #include +#ifdef DDB +#include +#include +#endif #include #include @@ -87,7 +92,6 @@ int lkmdebug = 0; #define LKMS_IDLE 0x00 #define LKMS_RESERVED 0x01 #define LKMS_LOADING 0x02 -#define LKMS_LOADED 0x04 #define LKMS_UNLOADING 0x08 static int lkm_v = 0; @@ -157,6 +161,10 @@ lkmunreserve() if (lkm_state == LKMS_IDLE) return; +#ifdef DDB + if (curp && curp->private.lkm_any && curp->private.lkm_any->lkm_name) + db_del_symbol_table(curp->private.lkm_any->lkm_name); +#endif /* * Actually unreserve the memory */ @@ -169,7 +177,15 @@ lkmunreserve() #endif curp->area = 0; } - + if (curp && curp->syms) { +#if defined(UVM) + uvm_km_free(kernel_map, curp->syms, curp->sym_size);/**/ +#else + /* XXXCDC: unwise to use kmem_map */ + kmem_free(kmem_map, curp->syms, curp->sym_size); +#endif + curp->syms = 0; + } lkm_state = LKMS_IDLE; } @@ -224,6 +240,7 @@ lkmioctl(dev, cmd, data, flag, p) switch(cmd) { case LMRESERV: /* reserve pages for a module */ + case LMRESERV_O: /* reserve pages for a module */ if (securelevel > 0) return EPERM; @@ -244,6 +261,7 @@ lkmioctl(dev, cmd, data, flag, p) } curp = &lkmods[i]; curp->id = i; /* self reference slot offset */ + curp->ver = (cmd == LMRESERV) ? LKM_VERSION : LKM_OLDVERSION; resrvp->slot = i; /* return slot */ @@ -263,10 +281,30 @@ lkmioctl(dev, cmd, data, flag, p) resrvp->addr = curp->area; /* ret kernel addr */ + if (cmd == LMRESERV && resrvp->sym_size) { + curp->sym_size = resrvp->sym_size; + curp->sym_symsize = resrvp->sym_symsize; +#if defined(UVM) + curp->syms = (u_long)uvm_km_alloc(kernel_map, curp->sym_size);/**/ +#else + curp->syms = (u_long)kmem_alloc(kmem_map, curp->sym_size);/**/ +#endif + curp->sym_offset = 0; + resrvp->sym_addr = curp->syms; /* ret symbol addr */ + } else { + curp->sym_size = 0; + curp->syms = 0; + curp->sym_offset = 0; + if (cmd == LMRESERV) + resrvp->sym_addr = 0; + } + #ifdef DEBUG if (lkmdebug & LKMDB_INFO) { printf("LKM: LMRESERV (actual = 0x%08lx)\n", curp->area); + printf("LKM: LMRESERV (syms = 0x%08lx)\n", + curp->syms); printf("LKM: LMRESERV (adjusted = 0x%08lx)\n", trunc_page(curp->area)); } @@ -303,17 +341,41 @@ lkmioctl(dev, cmd, data, flag, p) if (lkmdebug & LKMDB_LOAD) printf("LKM: LMLOADBUF (loading @ %ld of %ld, i = %d)\n", curp->offset, curp->size, i); -#endif /* DEBUG */ - } else { - lkm_state = LKMS_LOADED; -#ifdef DEBUG - if (lkmdebug & LKMDB_LOAD) - printf("LKM: LMLOADBUF (loaded)\n"); #endif /* DEBUG */ } curp->offset += i; break; + case LMLOADSYMS: /* Copy in; stateful, follows LMRESERV*/ + if ((flag & FWRITE) == 0) /* only allow this if writing */ + return EPERM; + + loadbufp = (struct lmc_loadbuf *)data; + i = loadbufp->cnt; + if ((lkm_state != LKMS_LOADING) + || i < 0 + || i > MODIOBUF + || i > curp->sym_size - curp->sym_offset) { + error = ENOMEM; + break; + } + + /* copy in buffer full of data*/ + if ((error = copyin(loadbufp->data, + (caddr_t)(curp->syms) + curp->sym_offset, + i)) != 0) + break; + + if ((curp->sym_offset + i) < curp->sym_size) { + lkm_state = LKMS_LOADING; +#ifdef DEBUG + printf( "LKM: LMLOADSYMS (loading @ %d of %d, i = %d)\n", + curp->sym_offset, curp->sym_size, i); +#endif /* DEBUG*/ + } + curp->sym_offset += i; + break; + case LMUNRESRV: /* discard reserved pages for a module */ if (securelevel > 0) return EPERM; @@ -329,22 +391,16 @@ lkmioctl(dev, cmd, data, flag, p) break; case LMREADY: /* module loaded: call entry */ +#ifdef DEBUG + printf("LKM: try READY"); +#endif /* DEBUG */ if (securelevel > 0) return EPERM; if ((flag & FWRITE) == 0) /* only allow this if writing */ return EPERM; - switch (lkm_state) { - case LKMS_LOADED: - break; - case LKMS_LOADING: - /* The remainder must be bss, so we clear it */ - memset((caddr_t)curp->area + curp->offset, 0, - curp->size - curp->offset); - break; - default: - + if (lkm_state != LKMS_LOADING) { #ifdef DEBUG if (lkmdebug & LKMDB_INFO) printf("lkm_state is %02x\n", lkm_state); @@ -352,11 +408,16 @@ lkmioctl(dev, cmd, data, flag, p) return ENXIO; } + if (curp->size - curp->offset > 0) + /* The remainder must be bss, so we clear it */ + memset((caddr_t)curp->area + curp->offset, 0, + curp->size - curp->offset); + curp->entry = (int (*) __P((struct lkm_table *, int, int))) (*((long *) (data))); /* call entry(load)... (assigns "private" portion) */ - error = (*(curp->entry))(curp, LKM_E_LOAD, LKM_VERSION); + error = (*(curp->entry))(curp, LKM_E_LOAD, curp->ver); if (error) { /* * Module may refuse loading or may have a @@ -373,6 +434,21 @@ lkmioctl(dev, cmd, data, flag, p) if (lkmdebug & LKMDB_INFO) printf("LKM: LMREADY\n"); #endif /* DEBUG */ +#ifdef DDB + if (curp->syms && curp->sym_offset >= curp->sym_size) { + db_add_symbol_table((caddr_t)curp->syms, + (caddr_t)curp->syms + curp->sym_symsize, + curp->private.lkm_any->lkm_name, + (caddr_t)curp->syms); +#ifdef DEBUG + if (lkmdebug & LKMDB_INFO) + printf( "DDB symbols added!\n" ); +#endif + } +#endif + + + lkm_state = LKMS_IDLE; break; @@ -423,7 +499,7 @@ lkmioctl(dev, cmd, data, flag, p) } /* call entry(unload) */ - if ((*(curp->entry))(curp, LKM_E_UNLOAD, LKM_VERSION)) { + if ((*(curp->entry))(curp, LKM_E_UNLOAD, curp->ver)) { error = EBUSY; break; } @@ -904,6 +980,10 @@ lkmdispatch(lkmtp, cmd) int cmd; { int error = 0; /* default = success */ +#ifdef DEBUG + if (lkmdebug & LKMDB_INFO) + printf( "lkmdispatch: %p %d\n", lkmtp, cmd ); +#endif switch(lkmtp->private.lkm_any->lkm_type) { case LM_SYSCALL: diff --git a/sys/sys/lkm.h b/sys/sys/lkm.h index 861dade9b5ee..230e07b69689 100644 --- a/sys/sys/lkm.h +++ b/sys/sys/lkm.h @@ -1,4 +1,4 @@ -/* $NetBSD: lkm.h,v 1.16 1997/05/28 02:44:57 thorpej Exp $ */ +/* $NetBSD: lkm.h,v 1.17 1999/01/13 23:06:28 sommerfe Exp $ */ /* * Header file used by loadable kernel modules and loadable kernel module @@ -53,6 +53,7 @@ typedef enum loadmod { } MODTYPE; +#define LKM_OLDVERSION 1 /* version of module loader */ #define LKM_VERSION 1 /* version of module loader */ #define MAXLKMNAME 32 @@ -188,6 +189,12 @@ struct lkm_table { int (*entry) __P((struct lkm_table *, int, int));/* entry function */ union lkm_generic private; /* module private data */ + + /* ddb support */ + u_long syms; /* start of symbol table */ + u_long sym_size; /* size of symbol table (syms+strings) */ + u_long sym_offset; /* offset of next symbol chunk */ + u_long sym_symsize; /* size of symbol part only */ }; @@ -283,14 +290,16 @@ extern int lkmdispatch __P((struct lkm_table *, int)); /* * IOCTL's recognized by /dev/lkm */ -#define LMRESERV _IOWR('K', 0, struct lmc_resrv) +#define LMRESERV_O _IOWR('K', 0, struct lmc_oresrv) #define LMLOADBUF _IOW('K', 1, struct lmc_loadbuf) #define LMUNRESRV _IO('K', 2) #define LMREADY _IOW('K', 3, int) +#define LMRESERV _IOWR('K', 4, struct lmc_resrv) #define LMLOAD _IOW('K', 9, struct lmc_load) #define LMUNLOAD _IOWR('K', 10, struct lmc_unload) #define LMSTAT _IOWR('K', 11, struct lmc_stat) +#define LMLOADSYMS _IOW('K', 12, struct lmc_loadbuf) #define MODIOBUF 512 /* # of bytes at a time to loadbuf */ @@ -307,8 +316,25 @@ struct lmc_resrv { char *name; /* IN: name (must be provided */ int slot; /* OUT: allocated slot (module ID) */ u_long addr; /* OUT: Link-to address */ + /* ddb support */ + u_long xxx_unused1; /* unused */ + u_long sym_size; /* IN: total size of symbol table */ + u_long xxx_unused2; /* unused */ + u_long sym_symsize; /* IN: size of symbol portion of symtable */ + u_long sym_addr; /* OUT: address of symbol table */ }; +/* + * (Compat with old kernels) + */ +struct lmc_oresrv { + u_long size; /* IN: size of module to reserve */ + char *name; /* IN: name (must be provided */ + int slot; /* OUT: allocated slot (module ID) */ + u_long addr; /* OUT: Link-to address */ +}; + + /* * Copy a buffer at a time into the allocated area in the kernel; writes