7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Copyright 2011 Joyent, Inc. All rights reserved.
28 * Copyright (c) 2012 by Delphix. All rights reserved.
29 */
30
31 #include <mdb/mdb_param.h>
32 #include <mdb/mdb_modapi.h>
33 #include <mdb/mdb_ctf.h>
34 #include <mdb/mdb_whatis.h>
35 #include <sys/cpuvar.h>
36 #include <sys/kmem_impl.h>
37 #include <sys/vmem_impl.h>
38 #include <sys/machelf.h>
39 #include <sys/modctl.h>
40 #include <sys/kobj.h>
41 #include <sys/panic.h>
42 #include <sys/stack.h>
43 #include <sys/sysmacros.h>
44 #include <vm/page.h>
45
46 #include "avl.h"
47 #include "combined.h"
2995 if (mdb_lookup_by_addr(bc.bc_stack[i],
2996 MDB_SYM_FUZZY, c, sizeof (c), &sym) == -1)
2997 continue;
2998 if (strncmp(c, "kmem_", 5) == 0)
2999 continue;
3000 mdb_printf(" %a\n", bc.bc_stack[i]);
3001 break;
3002 }
3003
3004 if (i >= depth)
3005 mdb_printf("\n");
3006 }
3007
3008 return (DCMD_OK);
3009 }
3010
3011 typedef struct kmem_verify {
3012 uint64_t *kmv_buf; /* buffer to read cache contents into */
3013 size_t kmv_size; /* number of bytes in kmv_buf */
3014 int kmv_corruption; /* > 0 if corruption found. */
3015 int kmv_besilent; /* report actual corruption sites */
3016 struct kmem_cache kmv_cache; /* the cache we're operating on */
3017 } kmem_verify_t;
3018
3019 /*
3020 * verify_pattern()
3021 * verify that buf is filled with the pattern pat.
3022 */
3023 static int64_t
3024 verify_pattern(uint64_t *buf_arg, size_t size, uint64_t pat)
3025 {
3026 /*LINTED*/
3027 uint64_t *bufend = (uint64_t *)((char *)buf_arg + size);
3028 uint64_t *buf;
3029
3030 for (buf = buf_arg; buf < bufend; buf++)
3031 if (*buf != pat)
3032 return ((uintptr_t)buf - (uintptr_t)buf_arg);
3033 return (-1);
3034 }
3035
3040 static int
3041 verify_buftag(kmem_buftag_t *btp, uintptr_t pat)
3042 {
3043 return (btp->bt_bxstat == ((intptr_t)btp->bt_bufctl ^ pat) ? 0 : -1);
3044 }
3045
3046 /*
3047 * verify_free()
3048 * verify the integrity of a free block of memory by checking
3049 * that it is filled with 0xdeadbeef and that its buftag is sane.
3050 */
3051 /*ARGSUSED1*/
3052 static int
3053 verify_free(uintptr_t addr, const void *data, void *private)
3054 {
3055 kmem_verify_t *kmv = (kmem_verify_t *)private;
3056 uint64_t *buf = kmv->kmv_buf; /* buf to validate */
3057 int64_t corrupt; /* corruption offset */
3058 kmem_buftag_t *buftagp; /* ptr to buftag */
3059 kmem_cache_t *cp = &kmv->kmv_cache;
3060 int besilent = kmv->kmv_besilent;
3061
3062 /*LINTED*/
3063 buftagp = KMEM_BUFTAG(cp, buf);
3064
3065 /*
3066 * Read the buffer to check.
3067 */
3068 if (mdb_vread(buf, kmv->kmv_size, addr) == -1) {
3069 if (!besilent)
3070 mdb_warn("couldn't read %p", addr);
3071 return (WALK_NEXT);
3072 }
3073
3074 if ((corrupt = verify_pattern(buf, cp->cache_verify,
3075 KMEM_FREE_PATTERN)) >= 0) {
3076 if (!besilent)
3077 mdb_printf("buffer %p (free) seems corrupted, at %p\n",
3078 addr, (uintptr_t)addr + corrupt);
3079 goto corrupt;
3080 }
3086 if ((cp->cache_flags & (KMF_HASH | KMF_LITE)) == KMF_HASH &&
3087 buftagp->bt_redzone != KMEM_REDZONE_PATTERN) {
3088 if (!besilent)
3089 mdb_printf("buffer %p (free) seems to "
3090 "have a corrupt redzone pattern\n", addr);
3091 goto corrupt;
3092 }
3093
3094 /*
3095 * confirm bufctl pointer integrity.
3096 */
3097 if (verify_buftag(buftagp, KMEM_BUFTAG_FREE) == -1) {
3098 if (!besilent)
3099 mdb_printf("buffer %p (free) has a corrupt "
3100 "buftag\n", addr);
3101 goto corrupt;
3102 }
3103
3104 return (WALK_NEXT);
3105 corrupt:
3106 kmv->kmv_corruption++;
3107 return (WALK_NEXT);
3108 }
3109
3110 /*
3111 * verify_alloc()
3112 * Verify that the buftag of an allocated buffer makes sense with respect
3113 * to the buffer.
3114 */
3115 /*ARGSUSED1*/
3116 static int
3117 verify_alloc(uintptr_t addr, const void *data, void *private)
3118 {
3119 kmem_verify_t *kmv = (kmem_verify_t *)private;
3120 kmem_cache_t *cp = &kmv->kmv_cache;
3121 uint64_t *buf = kmv->kmv_buf; /* buf to validate */
3122 /*LINTED*/
3123 kmem_buftag_t *buftagp = KMEM_BUFTAG(cp, buf);
3124 uint32_t *ip = (uint32_t *)buftagp;
3125 uint8_t *bp = (uint8_t *)buf;
3126 int looks_ok = 0, size_ok = 1; /* flags for finding corruption */
3127 int besilent = kmv->kmv_besilent;
3128
3129 /*
3130 * Read the buffer to check.
3131 */
3132 if (mdb_vread(buf, kmv->kmv_size, addr) == -1) {
3133 if (!besilent)
3134 mdb_warn("couldn't read %p", addr);
3135 return (WALK_NEXT);
3136 }
3137
3138 /*
3139 * There are two cases to handle:
3140 * 1. If the buf was alloc'd using kmem_cache_alloc, it will have
3141 * 0xfeedfacefeedface at the end of it
3142 * 2. If the buf was alloc'd using kmem_alloc, it will have
3143 * 0xbb just past the end of the region in use. At the buftag,
3144 * it will have 0xfeedface (or, if the whole buffer is in use,
3145 * 0xfeedface & bb000000 or 0xfeedfacf & 000000bb depending on
3146 * endianness), followed by 32 bits containing the offset of the
3147 * 0xbb byte in the buffer.
3165 "redzone size encoding\n", addr);
3166 goto corrupt;
3167 }
3168
3169 if (!looks_ok) {
3170 if (!besilent)
3171 mdb_printf("buffer %p (allocated) has a corrupt "
3172 "redzone signature\n", addr);
3173 goto corrupt;
3174 }
3175
3176 if (verify_buftag(buftagp, KMEM_BUFTAG_ALLOC) == -1) {
3177 if (!besilent)
3178 mdb_printf("buffer %p (allocated) has a "
3179 "corrupt buftag\n", addr);
3180 goto corrupt;
3181 }
3182
3183 return (WALK_NEXT);
3184 corrupt:
3185 kmv->kmv_corruption++;
3186 return (WALK_NEXT);
3187 }
3188
3189 /*ARGSUSED2*/
3190 int
3191 kmem_verify(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3192 {
3193 if (flags & DCMD_ADDRSPEC) {
3194 int check_alloc = 0, check_free = 0;
3195 kmem_verify_t kmv;
3196
3197 if (mdb_vread(&kmv.kmv_cache, sizeof (kmv.kmv_cache),
3198 addr) == -1) {
3199 mdb_warn("couldn't read kmem_cache %p", addr);
3200 return (DCMD_ERR);
3201 }
3202
3203 kmv.kmv_size = kmv.kmv_cache.cache_buftag +
3204 sizeof (kmem_buftag_t);
3205 kmv.kmv_buf = mdb_alloc(kmv.kmv_size, UM_SLEEP | UM_GC);
3206 kmv.kmv_corruption = 0;
3207
3208 if ((kmv.kmv_cache.cache_flags & KMF_REDZONE)) {
3209 check_alloc = 1;
3210 if (kmv.kmv_cache.cache_flags & KMF_DEADBEEF)
3211 check_free = 1;
3212 } else {
3213 if (!(flags & DCMD_LOOP)) {
3214 mdb_warn("cache %p (%s) does not have "
3215 "redzone checking enabled\n", addr,
3216 kmv.kmv_cache.cache_name);
3217 }
3218 return (DCMD_ERR);
3219 }
3220
3221 if (flags & DCMD_LOOP) {
3222 /*
3223 * table mode, don't print out every corrupt buffer
3224 */
3225 kmv.kmv_besilent = 1;
3226 } else {
3227 mdb_printf("Summary for cache '%s'\n",
3228 kmv.kmv_cache.cache_name);
3229 mdb_inc_indent(2);
3230 kmv.kmv_besilent = 0;
3231 }
3232
3233 if (check_alloc)
3234 (void) mdb_pwalk("kmem", verify_alloc, &kmv, addr);
3235 if (check_free)
3236 (void) mdb_pwalk("freemem", verify_free, &kmv, addr);
3237
3238 if (flags & DCMD_LOOP) {
3239 if (kmv.kmv_corruption == 0) {
3240 mdb_printf("%-*s %?p clean\n",
3241 KMEM_CACHE_NAMELEN,
3242 kmv.kmv_cache.cache_name, addr);
3243 } else {
3244 char *s = ""; /* optional s in "buffer[s]" */
3245 if (kmv.kmv_corruption > 1)
3246 s = "s";
3247
3248 mdb_printf("%-*s %?p %d corrupt buffer%s\n",
3249 KMEM_CACHE_NAMELEN,
3250 kmv.kmv_cache.cache_name, addr,
3251 kmv.kmv_corruption, s);
3252 }
3253 } else {
3254 /*
3255 * This is the more verbose mode, when the user has
3256 * type addr::kmem_verify. If the cache was clean,
3257 * nothing will have yet been printed. So say something.
3258 */
3259 if (kmv.kmv_corruption == 0)
3260 mdb_printf("clean\n");
3261
3262 mdb_dec_indent(2);
3263 }
3264 } else {
3265 /*
3266 * If the user didn't specify a cache to verify, we'll walk all
3267 * kmem_cache's, specifying ourself as a callback for each...
3268 * this is the equivalent of '::walk kmem_cache .::kmem_verify'
3269 */
3270 mdb_printf("%<u>%-*s %-?s %-20s%</b>\n", KMEM_CACHE_NAMELEN,
3271 "Cache Name", "Addr", "Cache Integrity");
3272 (void) (mdb_walk_dcmd("kmem_cache", "kmem_verify", 0, NULL));
3273 }
3274
3275 return (DCMD_OK);
3276 }
3277
3278 typedef struct vmem_node {
3279 struct vmem_node *vn_next;
3280 struct vmem_node *vn_parent;
3281 struct vmem_node *vn_sibling;
3282 struct vmem_node *vn_children;
3283 uintptr_t vn_addr;
3284 int vn_marked;
3285 vmem_t vn_vmem;
3286 } vmem_node_t;
3287
3288 typedef struct vmem_walk {
3289 vmem_node_t *vw_root;
3290 vmem_node_t *vw_current;
3291 } vmem_walk_t;
|
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Copyright 2018 Joyent, Inc. All rights reserved.
28 * Copyright (c) 2012 by Delphix. All rights reserved.
29 */
30
31 #include <mdb/mdb_param.h>
32 #include <mdb/mdb_modapi.h>
33 #include <mdb/mdb_ctf.h>
34 #include <mdb/mdb_whatis.h>
35 #include <sys/cpuvar.h>
36 #include <sys/kmem_impl.h>
37 #include <sys/vmem_impl.h>
38 #include <sys/machelf.h>
39 #include <sys/modctl.h>
40 #include <sys/kobj.h>
41 #include <sys/panic.h>
42 #include <sys/stack.h>
43 #include <sys/sysmacros.h>
44 #include <vm/page.h>
45
46 #include "avl.h"
47 #include "combined.h"
2995 if (mdb_lookup_by_addr(bc.bc_stack[i],
2996 MDB_SYM_FUZZY, c, sizeof (c), &sym) == -1)
2997 continue;
2998 if (strncmp(c, "kmem_", 5) == 0)
2999 continue;
3000 mdb_printf(" %a\n", bc.bc_stack[i]);
3001 break;
3002 }
3003
3004 if (i >= depth)
3005 mdb_printf("\n");
3006 }
3007
3008 return (DCMD_OK);
3009 }
3010
3011 typedef struct kmem_verify {
3012 uint64_t *kmv_buf; /* buffer to read cache contents into */
3013 size_t kmv_size; /* number of bytes in kmv_buf */
3014 int kmv_corruption; /* > 0 if corruption found. */
3015 uint_t kmv_flags; /* dcmd flags */
3016 struct kmem_cache kmv_cache; /* the cache we're operating on */
3017 } kmem_verify_t;
3018
3019 /*
3020 * verify_pattern()
3021 * verify that buf is filled with the pattern pat.
3022 */
3023 static int64_t
3024 verify_pattern(uint64_t *buf_arg, size_t size, uint64_t pat)
3025 {
3026 /*LINTED*/
3027 uint64_t *bufend = (uint64_t *)((char *)buf_arg + size);
3028 uint64_t *buf;
3029
3030 for (buf = buf_arg; buf < bufend; buf++)
3031 if (*buf != pat)
3032 return ((uintptr_t)buf - (uintptr_t)buf_arg);
3033 return (-1);
3034 }
3035
3040 static int
3041 verify_buftag(kmem_buftag_t *btp, uintptr_t pat)
3042 {
3043 return (btp->bt_bxstat == ((intptr_t)btp->bt_bufctl ^ pat) ? 0 : -1);
3044 }
3045
3046 /*
3047 * verify_free()
3048 * verify the integrity of a free block of memory by checking
3049 * that it is filled with 0xdeadbeef and that its buftag is sane.
3050 */
3051 /*ARGSUSED1*/
3052 static int
3053 verify_free(uintptr_t addr, const void *data, void *private)
3054 {
3055 kmem_verify_t *kmv = (kmem_verify_t *)private;
3056 uint64_t *buf = kmv->kmv_buf; /* buf to validate */
3057 int64_t corrupt; /* corruption offset */
3058 kmem_buftag_t *buftagp; /* ptr to buftag */
3059 kmem_cache_t *cp = &kmv->kmv_cache;
3060 boolean_t besilent = !!(kmv->kmv_flags & (DCMD_LOOP | DCMD_PIPE_OUT));
3061
3062 /*LINTED*/
3063 buftagp = KMEM_BUFTAG(cp, buf);
3064
3065 /*
3066 * Read the buffer to check.
3067 */
3068 if (mdb_vread(buf, kmv->kmv_size, addr) == -1) {
3069 if (!besilent)
3070 mdb_warn("couldn't read %p", addr);
3071 return (WALK_NEXT);
3072 }
3073
3074 if ((corrupt = verify_pattern(buf, cp->cache_verify,
3075 KMEM_FREE_PATTERN)) >= 0) {
3076 if (!besilent)
3077 mdb_printf("buffer %p (free) seems corrupted, at %p\n",
3078 addr, (uintptr_t)addr + corrupt);
3079 goto corrupt;
3080 }
3086 if ((cp->cache_flags & (KMF_HASH | KMF_LITE)) == KMF_HASH &&
3087 buftagp->bt_redzone != KMEM_REDZONE_PATTERN) {
3088 if (!besilent)
3089 mdb_printf("buffer %p (free) seems to "
3090 "have a corrupt redzone pattern\n", addr);
3091 goto corrupt;
3092 }
3093
3094 /*
3095 * confirm bufctl pointer integrity.
3096 */
3097 if (verify_buftag(buftagp, KMEM_BUFTAG_FREE) == -1) {
3098 if (!besilent)
3099 mdb_printf("buffer %p (free) has a corrupt "
3100 "buftag\n", addr);
3101 goto corrupt;
3102 }
3103
3104 return (WALK_NEXT);
3105 corrupt:
3106 if (kmv->kmv_flags & DCMD_PIPE_OUT)
3107 mdb_printf("%p\n", addr);
3108 kmv->kmv_corruption++;
3109 return (WALK_NEXT);
3110 }
3111
3112 /*
3113 * verify_alloc()
3114 * Verify that the buftag of an allocated buffer makes sense with respect
3115 * to the buffer.
3116 */
3117 /*ARGSUSED1*/
3118 static int
3119 verify_alloc(uintptr_t addr, const void *data, void *private)
3120 {
3121 kmem_verify_t *kmv = (kmem_verify_t *)private;
3122 kmem_cache_t *cp = &kmv->kmv_cache;
3123 uint64_t *buf = kmv->kmv_buf; /* buf to validate */
3124 /*LINTED*/
3125 kmem_buftag_t *buftagp = KMEM_BUFTAG(cp, buf);
3126 uint32_t *ip = (uint32_t *)buftagp;
3127 uint8_t *bp = (uint8_t *)buf;
3128 int looks_ok = 0, size_ok = 1; /* flags for finding corruption */
3129 boolean_t besilent = !!(kmv->kmv_flags & (DCMD_LOOP | DCMD_PIPE_OUT));
3130
3131 /*
3132 * Read the buffer to check.
3133 */
3134 if (mdb_vread(buf, kmv->kmv_size, addr) == -1) {
3135 if (!besilent)
3136 mdb_warn("couldn't read %p", addr);
3137 return (WALK_NEXT);
3138 }
3139
3140 /*
3141 * There are two cases to handle:
3142 * 1. If the buf was alloc'd using kmem_cache_alloc, it will have
3143 * 0xfeedfacefeedface at the end of it
3144 * 2. If the buf was alloc'd using kmem_alloc, it will have
3145 * 0xbb just past the end of the region in use. At the buftag,
3146 * it will have 0xfeedface (or, if the whole buffer is in use,
3147 * 0xfeedface & bb000000 or 0xfeedfacf & 000000bb depending on
3148 * endianness), followed by 32 bits containing the offset of the
3149 * 0xbb byte in the buffer.
3167 "redzone size encoding\n", addr);
3168 goto corrupt;
3169 }
3170
3171 if (!looks_ok) {
3172 if (!besilent)
3173 mdb_printf("buffer %p (allocated) has a corrupt "
3174 "redzone signature\n", addr);
3175 goto corrupt;
3176 }
3177
3178 if (verify_buftag(buftagp, KMEM_BUFTAG_ALLOC) == -1) {
3179 if (!besilent)
3180 mdb_printf("buffer %p (allocated) has a "
3181 "corrupt buftag\n", addr);
3182 goto corrupt;
3183 }
3184
3185 return (WALK_NEXT);
3186 corrupt:
3187 if (kmv->kmv_flags & DCMD_PIPE_OUT)
3188 mdb_printf("%p\n", addr);
3189
3190 kmv->kmv_corruption++;
3191 return (WALK_NEXT);
3192 }
3193
3194 /*ARGSUSED2*/
3195 int
3196 kmem_verify(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3197 {
3198 if (flags & DCMD_ADDRSPEC) {
3199 int check_alloc = 0, check_free = 0;
3200 kmem_verify_t kmv;
3201
3202 if (mdb_vread(&kmv.kmv_cache, sizeof (kmv.kmv_cache),
3203 addr) == -1) {
3204 mdb_warn("couldn't read kmem_cache %p", addr);
3205 return (DCMD_ERR);
3206 }
3207
3208 if ((kmv.kmv_cache.cache_dump.kd_unsafe ||
3209 kmv.kmv_cache.cache_dump.kd_alloc_fails) &&
3210 !(flags & (DCMD_LOOP | DCMD_PIPE_OUT))) {
3211 mdb_warn("WARNING: cache was used during dump: "
3212 "corruption may be incorrectly reported\n");
3213 }
3214
3215 kmv.kmv_size = kmv.kmv_cache.cache_buftag +
3216 sizeof (kmem_buftag_t);
3217 kmv.kmv_buf = mdb_alloc(kmv.kmv_size, UM_SLEEP | UM_GC);
3218 kmv.kmv_corruption = 0;
3219 kmv.kmv_flags = flags;
3220
3221 if ((kmv.kmv_cache.cache_flags & KMF_REDZONE)) {
3222 check_alloc = 1;
3223 if (kmv.kmv_cache.cache_flags & KMF_DEADBEEF)
3224 check_free = 1;
3225 } else {
3226 if (!(flags & DCMD_LOOP)) {
3227 mdb_warn("cache %p (%s) does not have "
3228 "redzone checking enabled\n", addr,
3229 kmv.kmv_cache.cache_name);
3230 }
3231 return (DCMD_ERR);
3232 }
3233
3234 if (!(flags & (DCMD_LOOP | DCMD_PIPE_OUT))) {
3235 mdb_printf("Summary for cache '%s'\n",
3236 kmv.kmv_cache.cache_name);
3237 mdb_inc_indent(2);
3238 }
3239
3240 if (check_alloc)
3241 (void) mdb_pwalk("kmem", verify_alloc, &kmv, addr);
3242 if (check_free)
3243 (void) mdb_pwalk("freemem", verify_free, &kmv, addr);
3244
3245 if (!(flags & DCMD_PIPE_OUT)) {
3246 if (flags & DCMD_LOOP) {
3247 if (kmv.kmv_corruption == 0) {
3248 mdb_printf("%-*s %?p clean\n",
3249 KMEM_CACHE_NAMELEN,
3250 kmv.kmv_cache.cache_name, addr);
3251 } else {
3252 mdb_printf("%-*s %?p %d corrupt "
3253 "buffer%s\n", KMEM_CACHE_NAMELEN,
3254 kmv.kmv_cache.cache_name, addr,
3255 kmv.kmv_corruption,
3256 kmv.kmv_corruption > 1 ? "s" : "");
3257 }
3258 } else {
3259 /*
3260 * This is the more verbose mode, when the user
3261 * typed addr::kmem_verify. If the cache was
3262 * clean, nothing will have yet been printed. So
3263 * say something.
3264 */
3265 if (kmv.kmv_corruption == 0)
3266 mdb_printf("clean\n");
3267
3268 mdb_dec_indent(2);
3269 }
3270 }
3271 } else {
3272 /*
3273 * If the user didn't specify a cache to verify, we'll walk all
3274 * kmem_cache's, specifying ourself as a callback for each...
3275 * this is the equivalent of '::walk kmem_cache .::kmem_verify'
3276 */
3277
3278 if (!(flags & DCMD_PIPE_OUT)) {
3279 uintptr_t dump_curr;
3280 uintptr_t dump_end;
3281
3282 if (mdb_readvar(&dump_curr, "kmem_dump_curr") != -1 &&
3283 mdb_readvar(&dump_end, "kmem_dump_end") != -1 &&
3284 dump_curr == dump_end) {
3285 mdb_warn("WARNING: exceeded kmem_dump_size; "
3286 "corruption may be incorrectly reported\n");
3287 }
3288
3289 mdb_printf("%<u>%-*s %-?s %-20s%</b>\n",
3290 KMEM_CACHE_NAMELEN, "Cache Name", "Addr",
3291 "Cache Integrity");
3292 }
3293
3294 (void) (mdb_walk_dcmd("kmem_cache", "kmem_verify", 0, NULL));
3295 }
3296
3297 return (DCMD_OK);
3298 }
3299
3300 typedef struct vmem_node {
3301 struct vmem_node *vn_next;
3302 struct vmem_node *vn_parent;
3303 struct vmem_node *vn_sibling;
3304 struct vmem_node *vn_children;
3305 uintptr_t vn_addr;
3306 int vn_marked;
3307 vmem_t vn_vmem;
3308 } vmem_node_t;
3309
3310 typedef struct vmem_walk {
3311 vmem_node_t *vw_root;
3312 vmem_node_t *vw_current;
3313 } vmem_walk_t;
|