Home | History | Annotate | Download | only in os
      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