1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/vmem.h> 30 #include <sys/kmem.h> 31 #include <sys/param.h> 32 #include <sys/sysmacros.h> 33 #include <sys/cmn_err.h> 34 #include <vm/seg_kmem.h> 35 36 static vmem_t *id32_arena; 37 static kmem_cache_t *id32_cache; 38 39 #define ID32_BITS 5 40 #define ID32_ALIGN (1 << ID32_BITS) 41 #define ID32_MOD (ID32_ALIGN - 1) 42 43 #if defined(__amd64) 44 /* 45 * For amd64 the 32 bit id is the offset of the entry in the arena. 46 */ 47 extern char *heap_core_base; 48 #define ID32_ENCODE(x) (((x) - (uintptr_t)heap_core_base) | \ 49 ((((x) - (uintptr_t)heap_core_base) % ID32_MOD)) + 1) 50 #define ID32_DECODE(x) (P2ALIGN((x), (uintptr_t)ID32_ALIGN) + \ 51 (uintptr_t)heap_core_base) 52 #define ID32_VALID(x) (ID32_ENCODE(ID32_DECODE(x)) == (x)) 53 #else /* __amd64 */ 54 /* 55 * All other architectures use the 32 bit pointer value for the 32 bit id. 56 */ 57 #define ID32_ENCODE(x) (((x) | ((x) % ID32_MOD)) + 1) 58 #define ID32_DECODE(x) P2ALIGN((x), ID32_ALIGN) 59 #define ID32_VALID(x) (ID32_ENCODE(ID32_DECODE(x)) == (x)) 60 #endif /* __amd64 */ 61 62 void 63 id32_init(void) 64 { 65 id32_arena = vmem_create("id32", NULL, 0, PAGESIZE, 66 segkmem_alloc, segkmem_free, heap32_arena, 0, VM_SLEEP); 67 68 id32_cache = kmem_cache_create("id32_cache", ID32_ALIGN, ID32_ALIGN, 69 NULL, NULL, NULL, NULL, id32_arena, 0); 70 } 71 72 /* 73 * Return a 32-bit identifier for the specified pointer. 74 */ 75 uint32_t 76 id32_alloc(void *ptr, int kmflag) 77 { 78 void **hent = kmem_cache_alloc(id32_cache, kmflag); 79 uintptr_t id; 80 81 if (hent == NULL) 82 return (0); 83 84 *hent = ptr; 85 id = ID32_ENCODE((uintptr_t)hent); 86 ASSERT64(id <= UINT32_MAX); 87 return ((uint32_t)id); 88 } 89 90 /* 91 * Free a 32-bit ID. 92 */ 93 void 94 id32_free(uint32_t id) 95 { 96 if (!ID32_VALID(id)) { 97 cmn_err(CE_WARN, "id32_free(%x): bad ID rejected\n", id); 98 return; 99 } 100 101 kmem_cache_free(id32_cache, (void *)(uintptr_t)ID32_DECODE(id)); 102 } 103 104 /* 105 * Return the pointer described by a 32-bit ID, or NULL if the ID is bad. 106 */ 107 void * 108 id32_lookup(uint32_t id) 109 { 110 if (!ID32_VALID(id)) { 111 cmn_err(CE_WARN, "id32_lookup(%x): bad ID rejected\n", id); 112 return (NULL); 113 } 114 115 return (((void **)(uintptr_t)ID32_DECODE(id))[0]); 116 } 117