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 #include <sys/vmem.h> 28 #include <sys/kmem.h> 29 #include <sys/param.h> 30 #include <sys/sysmacros.h> 31 #include <sys/cmn_err.h> 32 #include <vm/seg_kmem.h> 33 34 static vmem_t *id32_arena; 35 static kmem_cache_t *id32_cache; 36 37 #define ID32_BITS 5 38 #define ID32_ALIGN (1 << ID32_BITS) 39 #define ID32_MOD (ID32_ALIGN - 1) 40 41 #if defined(__amd64) 42 /* 43 * For amd64 the 32 bit id is the offset of the entry in the arena. 44 */ 45 extern char *heap_core_base; 46 #define ID32_ENCODE(x) (((x) - (uintptr_t)heap_core_base) | \ 47 ((((x) - (uintptr_t)heap_core_base) % ID32_MOD)) + 1) 48 #define ID32_DECODE(x) (P2ALIGN((x), (uintptr_t)ID32_ALIGN) + \ 49 (uintptr_t)heap_core_base) 50 #define ID32_VALID(x) (ID32_ENCODE(ID32_DECODE(x)) == (x)) 51 #else /* __amd64 */ 52 /* 53 * All other architectures use the 32 bit pointer value for the 32 bit id. 54 */ 55 #define ID32_ENCODE(x) (((x) | ((x) % ID32_MOD)) + 1) 56 #define ID32_DECODE(x) P2ALIGN((x), ID32_ALIGN) 57 #define ID32_VALID(x) (ID32_ENCODE(ID32_DECODE(x)) == (x)) 58 #endif /* __amd64 */ 59 60 void 61 id32_init(void) 62 { 63 id32_arena = vmem_create("id32", NULL, 0, PAGESIZE, 64 segkmem_alloc, segkmem_free, heap32_arena, 0, VM_SLEEP); 65 66 id32_cache = kmem_cache_create("id32_cache", ID32_ALIGN, ID32_ALIGN, 67 NULL, NULL, NULL, NULL, id32_arena, 0); 68 } 69 70 /* 71 * Return a 32-bit identifier for the specified pointer. 72 */ 73 uint32_t 74 id32_alloc(void *ptr, int kmflag) 75 { 76 void **hent = kmem_cache_alloc(id32_cache, kmflag); 77 uintptr_t id; 78 79 if (hent == NULL) 80 return (0); 81 82 *hent = ptr; 83 id = ID32_ENCODE((uintptr_t)hent); 84 ASSERT64(id <= UINT32_MAX); 85 return ((uint32_t)id); 86 } 87 88 /* 89 * Free a 32-bit ID. 90 */ 91 void 92 id32_free(uint32_t id) 93 { 94 if (!ID32_VALID(id)) { 95 cmn_err(CE_WARN, "id32_free(%x): bad ID rejected\n", id); 96 return; 97 } 98 99 kmem_cache_free(id32_cache, (void *)(uintptr_t)ID32_DECODE(id)); 100 } 101 102 /* 103 * Return the pointer described by a 32-bit ID, or NULL if the ID is bad. 104 */ 105 void * 106 id32_lookup(uint32_t id) 107 { 108 if (!ID32_VALID(id)) { 109 cmn_err(CE_WARN, "id32_lookup(%x): bad ID rejected\n", id); 110 return (NULL); 111 } 112 113 return (((void **)(uintptr_t)ID32_DECODE(id))[0]); 114 } 115