1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 30*7c478bd9Sstevel@tonic-gate #include <assert.h> 31*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 32*7c478bd9Sstevel@tonic-gate #include "rcapd_mapping.h" 33*7c478bd9Sstevel@tonic-gate #include "utils.h" 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate /* 36*7c478bd9Sstevel@tonic-gate * lmapping_t is a list of non-overlapping mappings, ordered by address. These 37*7c478bd9Sstevel@tonic-gate * functions add, remove, and verify the existence of mappings in such a list. 38*7c478bd9Sstevel@tonic-gate * rcapd_scanner.c is a consumer. 39*7c478bd9Sstevel@tonic-gate */ 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate typedef struct lmapping_find_cb_arg { 42*7c478bd9Sstevel@tonic-gate uintptr_t lmfa_addr; 43*7c478bd9Sstevel@tonic-gate size_t lmfa_size; 44*7c478bd9Sstevel@tonic-gate lmapping_t *lmfa_prior; 45*7c478bd9Sstevel@tonic-gate lmapping_t *lmfa_ret; 46*7c478bd9Sstevel@tonic-gate } lmapping_find_cb_arg_t; 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 49*7c478bd9Sstevel@tonic-gate /* 50*7c478bd9Sstevel@tonic-gate * Verify a sublist is properly ordered. 51*7c478bd9Sstevel@tonic-gate */ 52*7c478bd9Sstevel@tonic-gate static void 53*7c478bd9Sstevel@tonic-gate lmapping_verify(lmapping_t *lm) 54*7c478bd9Sstevel@tonic-gate { 55*7c478bd9Sstevel@tonic-gate while (lm != NULL) { 56*7c478bd9Sstevel@tonic-gate if (lm->lm_next != NULL) 57*7c478bd9Sstevel@tonic-gate ASSERT(lm->lm_next->lm_addr > lm->lm_addr); 58*7c478bd9Sstevel@tonic-gate lm = lm->lm_next; 59*7c478bd9Sstevel@tonic-gate } 60*7c478bd9Sstevel@tonic-gate } 61*7c478bd9Sstevel@tonic-gate #else /* !DEBUG */ 62*7c478bd9Sstevel@tonic-gate #define lmapping_verify(x) ((void)0) 63*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate /* 66*7c478bd9Sstevel@tonic-gate * Determine the position of a mapping with the given address and size. Upon 67*7c478bd9Sstevel@tonic-gate * return, lmfa_ret will be set to the actual mapping, if it exists, and 68*7c478bd9Sstevel@tonic-gate * lmfa_prior will be set to the mapping which does or would precede one with 69*7c478bd9Sstevel@tonic-gate * the given characteristics. 70*7c478bd9Sstevel@tonic-gate */ 71*7c478bd9Sstevel@tonic-gate static int 72*7c478bd9Sstevel@tonic-gate lmapping_find_cb(lmapping_t *lm, void *arg) 73*7c478bd9Sstevel@tonic-gate { 74*7c478bd9Sstevel@tonic-gate lmapping_find_cb_arg_t *lmfa = arg; 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate if (lm->lm_addr >= lmfa->lmfa_addr) { 77*7c478bd9Sstevel@tonic-gate if (lmfa->lmfa_addr == lm->lm_addr && lmfa->lmfa_size == 78*7c478bd9Sstevel@tonic-gate lm->lm_size) 79*7c478bd9Sstevel@tonic-gate lmfa->lmfa_ret = lm; 80*7c478bd9Sstevel@tonic-gate return (1); 81*7c478bd9Sstevel@tonic-gate } else 82*7c478bd9Sstevel@tonic-gate lmfa->lmfa_prior = lm; 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate return (0); 85*7c478bd9Sstevel@tonic-gate } 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate static void 88*7c478bd9Sstevel@tonic-gate lmapping_walk(lmapping_t *lm, int(*lmapping_walk_cb)(lmapping_t *, void *), 89*7c478bd9Sstevel@tonic-gate void *arg) 90*7c478bd9Sstevel@tonic-gate { 91*7c478bd9Sstevel@tonic-gate lmapping_t *next; 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate while (lm != NULL) { 94*7c478bd9Sstevel@tonic-gate next = lm->lm_next; 95*7c478bd9Sstevel@tonic-gate lmapping_verify(lm); 96*7c478bd9Sstevel@tonic-gate if (lmapping_walk_cb(lm, arg) != 0) { 97*7c478bd9Sstevel@tonic-gate lmapping_verify(lm); 98*7c478bd9Sstevel@tonic-gate return; 99*7c478bd9Sstevel@tonic-gate } 100*7c478bd9Sstevel@tonic-gate lm = next; 101*7c478bd9Sstevel@tonic-gate } 102*7c478bd9Sstevel@tonic-gate } 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate int 105*7c478bd9Sstevel@tonic-gate lmapping_remove(lmapping_t **lm, uintptr_t addr, size_t size) 106*7c478bd9Sstevel@tonic-gate { 107*7c478bd9Sstevel@tonic-gate lmapping_find_cb_arg_t lmfa; 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate lmfa.lmfa_addr = addr; 110*7c478bd9Sstevel@tonic-gate lmfa.lmfa_size = size; 111*7c478bd9Sstevel@tonic-gate lmfa.lmfa_prior = lmfa.lmfa_ret = NULL; 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate lmapping_verify(*lm); 114*7c478bd9Sstevel@tonic-gate lmapping_walk(*lm, lmapping_find_cb, &lmfa); 115*7c478bd9Sstevel@tonic-gate if (lmfa.lmfa_ret == NULL) 116*7c478bd9Sstevel@tonic-gate return (-1); 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate if (lmfa.lmfa_prior != NULL) 119*7c478bd9Sstevel@tonic-gate lmfa.lmfa_prior->lm_next = lmfa.lmfa_ret->lm_next; 120*7c478bd9Sstevel@tonic-gate else if (*lm == lmfa.lmfa_ret) 121*7c478bd9Sstevel@tonic-gate *lm = lmfa.lmfa_ret->lm_next; 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate free(lmfa.lmfa_ret); 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate lmapping_verify(*lm); 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate return (0); 128*7c478bd9Sstevel@tonic-gate } 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate int 131*7c478bd9Sstevel@tonic-gate lmapping_insert(lmapping_t **lm, uintptr_t addr, size_t size) 132*7c478bd9Sstevel@tonic-gate { 133*7c478bd9Sstevel@tonic-gate lmapping_find_cb_arg_t lmfa; 134*7c478bd9Sstevel@tonic-gate lmapping_t *cur; 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate cur = malloc(sizeof (*cur)); 137*7c478bd9Sstevel@tonic-gate if (cur == NULL) 138*7c478bd9Sstevel@tonic-gate return (-1); 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate cur->lm_addr = addr; 141*7c478bd9Sstevel@tonic-gate cur->lm_size = size; 142*7c478bd9Sstevel@tonic-gate cur->lm_next = NULL; 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate lmfa.lmfa_addr = addr; 145*7c478bd9Sstevel@tonic-gate lmfa.lmfa_size = size; 146*7c478bd9Sstevel@tonic-gate lmfa.lmfa_prior = lmfa.lmfa_ret = NULL; 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate lmapping_verify(*lm); 149*7c478bd9Sstevel@tonic-gate lmapping_walk(*lm, lmapping_find_cb, &lmfa); 150*7c478bd9Sstevel@tonic-gate ASSERT(lmfa.lmfa_ret == NULL); 151*7c478bd9Sstevel@tonic-gate if (lmfa.lmfa_prior != NULL) { 152*7c478bd9Sstevel@tonic-gate cur->lm_next = lmfa.lmfa_prior->lm_next; 153*7c478bd9Sstevel@tonic-gate lmfa.lmfa_prior->lm_next = cur; 154*7c478bd9Sstevel@tonic-gate } else { 155*7c478bd9Sstevel@tonic-gate cur->lm_next = *lm; 156*7c478bd9Sstevel@tonic-gate *lm = cur; 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate lmapping_verify(*lm); 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate return (0); 162*7c478bd9Sstevel@tonic-gate } 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate int 165*7c478bd9Sstevel@tonic-gate lmapping_contains(lmapping_t *lm, uintptr_t addr, size_t size) 166*7c478bd9Sstevel@tonic-gate { 167*7c478bd9Sstevel@tonic-gate lmapping_find_cb_arg_t lmfa; 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate lmfa.lmfa_addr = addr; 170*7c478bd9Sstevel@tonic-gate lmfa.lmfa_size = size; 171*7c478bd9Sstevel@tonic-gate lmfa.lmfa_ret = NULL; 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate lmapping_walk(lm, lmapping_find_cb, &lmfa); 174*7c478bd9Sstevel@tonic-gate return (lmfa.lmfa_ret != NULL); 175*7c478bd9Sstevel@tonic-gate } 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 178*7c478bd9Sstevel@tonic-gate static int 179*7c478bd9Sstevel@tonic-gate lmapping_free_cb(lmapping_t *lm, void *arg) 180*7c478bd9Sstevel@tonic-gate { 181*7c478bd9Sstevel@tonic-gate free(lm); 182*7c478bd9Sstevel@tonic-gate return (0); 183*7c478bd9Sstevel@tonic-gate } 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate void 186*7c478bd9Sstevel@tonic-gate lmapping_free(lmapping_t **lm) 187*7c478bd9Sstevel@tonic-gate { 188*7c478bd9Sstevel@tonic-gate lmapping_walk(*lm, lmapping_free_cb, NULL); 189*7c478bd9Sstevel@tonic-gate *lm = NULL; 190*7c478bd9Sstevel@tonic-gate } 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 193*7c478bd9Sstevel@tonic-gate int 194*7c478bd9Sstevel@tonic-gate lmapping_dump_diff(lmapping_t *lm1, lmapping_t *lm2) 195*7c478bd9Sstevel@tonic-gate { 196*7c478bd9Sstevel@tonic-gate lmapping_t **lmv; 197*7c478bd9Sstevel@tonic-gate int res = 0; 198*7c478bd9Sstevel@tonic-gate int ch = 0; 199*7c478bd9Sstevel@tonic-gate int label_printed = 0; 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate #define OUTPUT_LABEL() \ 202*7c478bd9Sstevel@tonic-gate if (label_printed == 0) { \ 203*7c478bd9Sstevel@tonic-gate debug("changes in mappings:\n"); \ 204*7c478bd9Sstevel@tonic-gate label_printed++; \ 205*7c478bd9Sstevel@tonic-gate } 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate while (lm1 != NULL && lm2 != NULL) { 208*7c478bd9Sstevel@tonic-gate if ((lm1->lm_addr != lm2->lm_addr) || (lm1->lm_size != 209*7c478bd9Sstevel@tonic-gate lm2->lm_size)) { 210*7c478bd9Sstevel@tonic-gate res = -1; 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate if (lm1->lm_addr == lm2->lm_addr && lm1->lm_size < 213*7c478bd9Sstevel@tonic-gate lm2->lm_size || lm1->lm_addr < lm2->lm_addr) { 214*7c478bd9Sstevel@tonic-gate lmv = &lm1; 215*7c478bd9Sstevel@tonic-gate ch = '-'; 216*7c478bd9Sstevel@tonic-gate } else { 217*7c478bd9Sstevel@tonic-gate lmv = &lm2; 218*7c478bd9Sstevel@tonic-gate ch = '+'; 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate OUTPUT_LABEL(); 221*7c478bd9Sstevel@tonic-gate debug("%c%p+0x%llx\n", ch, (void *)(*lmv)->lm_addr, 222*7c478bd9Sstevel@tonic-gate (long long)(*lmv)->lm_size); 223*7c478bd9Sstevel@tonic-gate *lmv = (*lmv)->lm_next; 224*7c478bd9Sstevel@tonic-gate } else { 225*7c478bd9Sstevel@tonic-gate lm1 = lm1->lm_next; 226*7c478bd9Sstevel@tonic-gate lm2 = lm2->lm_next; 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate while (lm1 != NULL) { 230*7c478bd9Sstevel@tonic-gate OUTPUT_LABEL(); 231*7c478bd9Sstevel@tonic-gate debug("%c%p+0x%llx\n", '-', (void *)lm1->lm_addr, 232*7c478bd9Sstevel@tonic-gate (unsigned long long)lm1->lm_size); 233*7c478bd9Sstevel@tonic-gate lm1 = lm1->lm_next; 234*7c478bd9Sstevel@tonic-gate res = 1; 235*7c478bd9Sstevel@tonic-gate } 236*7c478bd9Sstevel@tonic-gate while (lm2 != NULL) { 237*7c478bd9Sstevel@tonic-gate OUTPUT_LABEL(); 238*7c478bd9Sstevel@tonic-gate debug("%c%p+0x%llx\n", '+', (void *)lm2->lm_addr, 239*7c478bd9Sstevel@tonic-gate (long long)lm2->lm_size); 240*7c478bd9Sstevel@tonic-gate lm2 = lm2->lm_next; 241*7c478bd9Sstevel@tonic-gate res = 1; 242*7c478bd9Sstevel@tonic-gate } 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate return (res); 245*7c478bd9Sstevel@tonic-gate #undef OUTPUT_LABEL 246*7c478bd9Sstevel@tonic-gate } 247*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 248