seg_xmem.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * CDDL HEADER START
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * The contents of this file are subject to the terms of the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Common Development and Distribution License, Version 1.0 only
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * (the "License"). You may not use this file except in compliance
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin * with the License.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * See the License for the specific language governing permissions
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * and limitations under the License.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * When distributing Covered Code, include this CDDL HEADER in each
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If applicable, add the following below this CDDL HEADER, with the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * fields enclosed by brackets "[]" replaced with your own identifying
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * information: Portions Copyright [yyyy] [name of copyright owner]
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * CDDL HEADER END
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Use is subject to license terms.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* All Rights Reserved */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Portions of this source code were derived from Berkeley 4.3 BSD
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * under license from the Regents of the University of California.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#pragma ident "%Z%%M% %I% %E% SMI"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The segxmem driver is used by the xmemfs to get faster (than seg_map)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * mappings [lower routine overhead] to random vnode/offsets.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Mappings are made to a very limited kernel address range and to a
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * potentially much larger user address range. It is the speed of mmap
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * and munmaps to the user address space that we are concerned with.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * We also need to ensure very low overhead for I/O similar to seg_spt
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * Private seg op routines.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int segxmem_dup(struct seg *seg, struct seg *newseg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int segxmem_unmap(struct seg *seg, caddr_t raddr, size_t ssize);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic faultcode_t segxmem_fault(struct hat *hat, struct seg *seg, caddr_t addr,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int segxmem_setprot(struct seg *seg, caddr_t addr, size_t len,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int segxmem_checkprot(struct seg *seg, caddr_t addr, size_t len,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic size_t segxmem_incore(struct seg *seg, caddr_t addr, size_t len,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *vec);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int segxmem_sync(struct seg *seg, register caddr_t addr, size_t len,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int segxmem_lockop(struct seg *seg, caddr_t addr, size_t len,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int segxmem_getprot(struct seg *seg, caddr_t addr, size_t len,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic u_offset_t segxmem_getoffset(struct seg *seg, caddr_t addr);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int segxmem_gettype(struct seg *seg, caddr_t addr);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int segxmem_getvp(struct seg *, caddr_t, struct vnode **);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int segxmem_advise(struct seg *seg, caddr_t addr, size_t len,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int segxmem_pagelock(struct seg *seg, caddr_t addr, size_t len,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int segxmem_setpgsz(struct seg *, caddr_t, size_t, uint_t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int segxmem_getmemid(struct seg *, caddr_t, memid_t *);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin segxmem_fault, /* Change if HAT_DYNAMIC_ISM_UNMAP suported */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SEGXMEM_NULLOP(lgrp_mem_policy_info_t *), /* getpolicy */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Statistics for segxmem operations.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * No explicit locking to protect these stats.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinkstat_named_t *segxmemcnt_ptr = (kstat_named_t *)&segxmemcnt;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinuint_t segxmemcnt_ndata = sizeof (segxmemcnt) / sizeof (kstat_named_t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinsegxmem_create(struct seg *seg, struct segxmem_crargs *xmem_a)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ASSERT(seg->s_as && RW_WRITE_HELD(&seg->s_as->a_lock));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (((uintptr_t)seg->s_base | seg->s_size) & PAGEOFFSET)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sxd = kmem_zalloc(sizeof (struct segxmem_data), KM_SLEEP);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin hat_memload_array(hat, taddr, tlen, ppp, prot | HAT_NOSYNC,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct segxmem_data *sxd = (struct segxmem_data *)seg->s_data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ASSERT(seg->s_as && RW_WRITE_HELD(&seg->s_as->a_lock));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct segxmem_data *sxd = (struct segxmem_data *)seg->s_data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin newsxd = kmem_zalloc(sizeof (struct segxmem_data), KM_SLEEP);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (vaddr = seg->s_base; vaddr < seg->s_base + seg->s_size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* ### sxd->sxd_vp->xn_ppa[(vaddr - s_base)]->p_pagenum */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; i < ppb; i++) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin hat_memload_array(newseg->s_as->a_hat, vaddr, sxd->sxd_bsize,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This routine is called via a machine specific fault handling
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * routine. It is also called by software routines wishing to
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * lock or unlock a range of addresses.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as, &seg->s_as->a_lock));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (type) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Because we know that every shared memory is
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * already locked and called in the same context.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Check for softlock
case F_INVAL:
return (FC_NOMAP);
case F_PROT:
return (FC_NOMAP);
return (IE_NOMEM);
if (pgno != 0) {
while (pgno != 0);
static u_offset_t
return (MAP_SHARED);
#ifdef lint
HAT_LOAD);
return (baseaddr);
#ifdef DEBUG
if (remap_broken)
(void *)taddr));
blocknumber++;
ppa++;
static size_t
#ifdef lint
return (len);
#ifdef lint
for (i = 0; i < nblocks; i++) {
for (j = 0; j < npages; j++) {
pfn++;
return (ENOTSUP);
return (ENOTSUP);
int len;
newval = 0;