seg_nf.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Portions of this source code were derived from Berkeley 4.3 BSD
* under license from the Regents of the University of California.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* VM - segment for non-faulting loads.
*/
#include <sys/archsystm.h>
/*
* Private seg op routines.
*/
static faultcode_t segnf_nomap(void);
static void segnf_badop(void);
static int segnf_nop(void);
enum fault_type, enum seg_rw))
segnf_nomap, /* fault */
segnf_nomap, /* faulta */
(int (*)())segnf_badop, /* kluster */
segnf_nop, /* sync */
segnf_nop, /* incore */
segnf_nop, /* lockop */
segnf_nop, /* advise */
};
/*
* vnode and page for the page of zeros we use for the nf mappings.
*/
static kmutex_t segnf_lock;
#define addr_to_vcolor(addr) \
(shm_alignment) ? \
/*
* We try to limit the number of Non-fault segments created.
* Non fault segments are created to optimize sparc V9 code which uses
* the sparc nonfaulting load ASI (ASI_PRIMARY_NOFAULT).
*
* There are several reasons why creating too many non-fault segments
* could cause problems.
*
* First, excessive allocation of kernel resources for the seg
* structures and the HAT data to map the zero pages.
*
* Secondly, creating nofault segments actually uses up user virtual
* address space. This makes it unavailable for subsequent mmap(0, ...)
* calls which use as_gap() to find empty va regions. Creation of too
* many nofault segments could thus interfere with the ability of the
* runtime linker to load a shared object.
*/
#define MAXSEGFORNF (10000)
#define MAXNFSEARCH (5)
/*
* Must be called from startup()
*/
void
{
}
/*
* Create a no-fault segment.
*
* The no-fault segment is not technically necessary, as the code in
* nfload() in trap.c will emulate the SPARC instruction and load
* a value of zero in the destination register.
*
* However, this code tries to put a page of zero's at the nofault address
* so that subsequent non-faulting loads to the same page will not
* trap with a tlb miss.
*
* In order to help limit the number of segments we merge adjacent nofault
* segments into a single segment. If we get a large number of segments
* we'll also try to delete a random other nf segment.
*/
/* ARGSUSED */
int
{
u_offset_t off = 0;
int i, color;
/*
* Need a page per virtual color or just 1 if no vac.
*/
vacpgs = 1;
if (shm_alignment > PAGESIZE) {
}
page_io_unlock(zpp[i]);
page_downgrade(zpp[i]);
}
}
/*
* s_data can't be NULL because of ASSERTS in the common vm code.
*/
/*
* At this point see if we can concatenate a segment to
*/
}
}
/*
* if we already have a lot of segments, try to delete some other
* nofault segment to reduce the probability of uncontrolled segment
* creation.
*
* the code looks around quickly (no more than MAXNFSEARCH segments
* each way) for another NF segment and then deletes it.
*/
size = 0;
}
}
}
}
return (0);
}
/*
* Never really need "No fault" segments, so they aren't dup'd.
*/
/* ARGSUSED */
static int
{
panic("segnf_dup");
return (0);
}
/*
* Split a segment at addr for length len.
*/
static int
{
/*
* Check for bad sizes.
*/
}
/*
* Unload any hardware translations in the range to be taken out.
*/
/*
* Freeing entire segment.
*/
/*
* Freeing the beginning of the segment.
*/
/*
* Freeing the end of the segment.
*/
} else {
/*
* The section to go is in the middle of the segment, so we
* have to cut it into two segments. We shrink the existing
* "seg" at the low end, and create "nseg" for the high end.
*/
/*
* Trim down "seg" before trying to stick "nseg" into the as.
*/
/*
* s_data can't be NULL because of ASSERTs in common VM code.
*/
}
return (0);
}
/*
* Free a segment.
*/
static void
{
}
/*
* No faults allowed on segnf.
*/
static faultcode_t
segnf_nomap(void)
{
return (FC_NOMAP);
}
/* ARGSUSED */
static int
{
return (EACCES);
}
/* ARGSUSED */
static int
{
}
static void
segnf_badop(void)
{
panic("segnf_badop");
/*NOTREACHED*/
}
static int
segnf_nop(void)
{
return (0);
}
static int
{
size_t p;
for (p = 0; p < pgno; ++p)
return (0);
}
/* ARGSUSED */
static u_offset_t
{
return ((u_offset_t)0);
}
/* ARGSUSED */
static int
{
return (MAP_SHARED);
}
/* ARGSUSED */
static int
{
return (0);
}
/*
* segnf pages are not dumped, so we just return
*/
/* ARGSUSED */
static void
{}
/*ARGSUSED*/
static int
{
return (ENOTSUP);
}
/*ARGSUSED*/
static int
{
return (ENOTSUP);
}
/*ARGSUSED*/
static int
{
return (ENODEV);
}
/*ARGSUSED*/
static lgrp_mem_policy_info_t *
{
return (NULL);
}