139f030b8SPatrick Mooney /*
239f030b8SPatrick Mooney  * This file and its contents are supplied under the terms of the
339f030b8SPatrick Mooney  * Common Development and Distribution License ("CDDL"), version 1.0.
439f030b8SPatrick Mooney  * You may only use this file in accordance with the terms of version
539f030b8SPatrick Mooney  * 1.0 of the CDDL.
639f030b8SPatrick Mooney  *
739f030b8SPatrick Mooney  * A full copy of the text of the CDDL should have accompanied this
839f030b8SPatrick Mooney  * source.  A copy of the CDDL is also available via the Internet at
939f030b8SPatrick Mooney  * http://www.illumos.org/license/CDDL.
1039f030b8SPatrick Mooney  */
1139f030b8SPatrick Mooney 
1239f030b8SPatrick Mooney /*
1339f030b8SPatrick Mooney  * Copyright 2016 Joyent, Inc.
1439f030b8SPatrick Mooney  */
1539f030b8SPatrick Mooney 
1639f030b8SPatrick Mooney #include "dnlc.h"
1739f030b8SPatrick Mooney 
1839f030b8SPatrick Mooney #include <mdb/mdb_modapi.h>
1939f030b8SPatrick Mooney #include <sys/dnlc.h>
2039f030b8SPatrick Mooney 
2139f030b8SPatrick Mooney typedef struct dnlc_walk {
2239f030b8SPatrick Mooney 	int dw_hashsz;
2339f030b8SPatrick Mooney 	int dw_index;
2439f030b8SPatrick Mooney 	uintptr_t dw_hash;
2539f030b8SPatrick Mooney 	uintptr_t dw_head;
2639f030b8SPatrick Mooney } dnlc_walk_t;
2739f030b8SPatrick Mooney 
2839f030b8SPatrick Mooney 
2939f030b8SPatrick Mooney int
dnlc_walk_init(mdb_walk_state_t * wsp)3039f030b8SPatrick Mooney dnlc_walk_init(mdb_walk_state_t *wsp)
3139f030b8SPatrick Mooney {
3239f030b8SPatrick Mooney 	dnlc_walk_t *dwp;
3339f030b8SPatrick Mooney 
34*892ad162SToomas Soome 	if (wsp->walk_addr != 0) {
3539f030b8SPatrick Mooney 		mdb_warn("dnlc walk doesn't support global walks\n");
3639f030b8SPatrick Mooney 		return (WALK_ERR);
3739f030b8SPatrick Mooney 	}
3839f030b8SPatrick Mooney 
3939f030b8SPatrick Mooney 	dwp = mdb_zalloc(sizeof (dnlc_walk_t), UM_SLEEP);
4039f030b8SPatrick Mooney 	if (mdb_readvar(&dwp->dw_hashsz, "nc_hashsz") == -1 ||
4139f030b8SPatrick Mooney 	    dwp->dw_hashsz <= 0) {
4239f030b8SPatrick Mooney 		mdb_warn("failed to read 'nc_hashsz'\n");
4339f030b8SPatrick Mooney 		mdb_free(dwp, sizeof (dnlc_walk_t));
4439f030b8SPatrick Mooney 		return (WALK_ERR);
4539f030b8SPatrick Mooney 	}
4639f030b8SPatrick Mooney 	if (dwp->dw_hashsz <= 0) {
4739f030b8SPatrick Mooney 		mdb_warn("invalid 'nc_hashsz' value\n");
4839f030b8SPatrick Mooney 		mdb_free(dwp, sizeof (dnlc_walk_t));
4939f030b8SPatrick Mooney 		return (WALK_ERR);
5039f030b8SPatrick Mooney 	}
5139f030b8SPatrick Mooney 	if (mdb_readvar(&dwp->dw_hash, "nc_hash") == -1) {
5239f030b8SPatrick Mooney 		mdb_warn("failed to read 'nc_hash'\n");
5339f030b8SPatrick Mooney 		mdb_free(dwp, sizeof (dnlc_walk_t));
5439f030b8SPatrick Mooney 		return (WALK_ERR);
5539f030b8SPatrick Mooney 	}
5639f030b8SPatrick Mooney 
5739f030b8SPatrick Mooney 	wsp->walk_data = dwp;
5839f030b8SPatrick Mooney 	return (WALK_NEXT);
5939f030b8SPatrick Mooney }
6039f030b8SPatrick Mooney 
6139f030b8SPatrick Mooney int
dnlc_walk_step(mdb_walk_state_t * wsp)6239f030b8SPatrick Mooney dnlc_walk_step(mdb_walk_state_t *wsp)
6339f030b8SPatrick Mooney {
6439f030b8SPatrick Mooney 	dnlc_walk_t *dwp = wsp->walk_data;
6539f030b8SPatrick Mooney 	nc_hash_t hash;
6639f030b8SPatrick Mooney 	uintptr_t result, addr = wsp->walk_addr;
6739f030b8SPatrick Mooney 
6839f030b8SPatrick Mooney next:
69*892ad162SToomas Soome 	while (addr == dwp->dw_head || addr == 0) {
7039f030b8SPatrick Mooney 		if (dwp->dw_index >= dwp->dw_hashsz) {
7139f030b8SPatrick Mooney 			return (WALK_DONE);
7239f030b8SPatrick Mooney 		}
7339f030b8SPatrick Mooney 		dwp->dw_head = dwp->dw_hash +
7439f030b8SPatrick Mooney 		    (sizeof (nc_hash_t) * dwp->dw_index);
7539f030b8SPatrick Mooney 		if (mdb_vread(&hash, sizeof (hash), dwp->dw_head) == -1) {
7639f030b8SPatrick Mooney 			mdb_warn("failed to read nc_hash_t at %#lx",
7739f030b8SPatrick Mooney 			    dwp->dw_hash);
7839f030b8SPatrick Mooney 			return (WALK_ERR);
7939f030b8SPatrick Mooney 		}
8039f030b8SPatrick Mooney 		dwp->dw_index++;
8139f030b8SPatrick Mooney 		addr = (uintptr_t)hash.hash_next;
8239f030b8SPatrick Mooney 	}
8339f030b8SPatrick Mooney 
8439f030b8SPatrick Mooney 	result = addr;
8539f030b8SPatrick Mooney 	if (mdb_vread(&addr, sizeof (uintptr_t), addr) == -1) {
8639f030b8SPatrick Mooney 		/*
8739f030b8SPatrick Mooney 		 * This entry may have become bogus since acquiring the address
8839f030b8SPatrick Mooney 		 * from its neighbor.  Continue on if that is the case.
8939f030b8SPatrick Mooney 		 */
90*892ad162SToomas Soome 		addr = 0;
9139f030b8SPatrick Mooney 		goto next;
9239f030b8SPatrick Mooney 	}
9339f030b8SPatrick Mooney 	wsp->walk_addr = addr;
9439f030b8SPatrick Mooney 
9539f030b8SPatrick Mooney 	return (wsp->walk_callback(result, &result, wsp->walk_cbdata));
9639f030b8SPatrick Mooney }
9739f030b8SPatrick Mooney 
9839f030b8SPatrick Mooney void
dnlc_walk_fini(mdb_walk_state_t * wsp)9939f030b8SPatrick Mooney dnlc_walk_fini(mdb_walk_state_t *wsp)
10039f030b8SPatrick Mooney {
10139f030b8SPatrick Mooney 	dnlc_walk_t *dwp = wsp->walk_data;
10239f030b8SPatrick Mooney 
10339f030b8SPatrick Mooney 	mdb_free(dwp, sizeof (dnlc_walk_t));
10439f030b8SPatrick Mooney }
105